5 #ifndef BITCOIN_SCRIPT_MINISCRIPT_H 6 #define BITCOIN_SCRIPT_MINISCRIPT_H 137 friend consteval
Type operator""_mst(
const char* c,
size_t l);
159 inline consteval
Type operator""_mst(
const char* c,
size_t l)
163 for (
const char *p = c; p < c + l; p++) {
175 *p ==
'f' ? 1 << 10 :
176 *p ==
's' ? 1 << 11 :
177 *p ==
'm' ? 1 << 12 :
178 *p ==
'x' ? 1 << 13 :
179 *p ==
'g' ? 1 << 14 :
180 *p ==
'h' ? 1 << 15 :
181 *p ==
'i' ? 1 << 16 :
182 *p ==
'j' ? 1 << 17 :
183 *p ==
'k' ? 1 << 18 :
184 (
throw std::logic_error(
"Unknown character in _mst literal"), 0)
191 using Opcode = std::pair<opcodetype, std::vector<unsigned char>>;
193 template<
typename Key>
class Node;
196 template <
typename Key, std::invocable<const Node<Key>&> Fn>
199 std::vector<std::reference_wrapper<const Node<Key>>> stack{root};
200 while (!stack.empty()) {
202 std::invoke(fn,
node);
204 for (
const auto& sub :
node.Subs()) {
205 stack.emplace_back(sub);
323 std::vector<std::vector<unsigned char>>
stack;
357 template<
typename A,
typename B>
362 template <
typename I>
381 if (!a.
valid)
return b;
382 if (!b.
valid)
return a;
453 constexpr
SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept :
464 if (!a.valid)
return b;
465 if (!b.valid)
return a;
467 return {std::max(a.netdiff, b.netdiff), std::max(a.exec, b.exec)};
474 if (!a.valid || !b.valid)
return {};
478 return {a.
netdiff + b.netdiff, std::max(b.exec, b.netdiff + a.exec)};
490 static constexpr
SatInfo If() noexcept {
return {1, 1}; }
496 static constexpr
SatInfo OP_IFDUP(
bool nonzero) noexcept {
return {nonzero ? -1 : 0, 0}; }
531 template <
typename Key>
541 std::vector<unsigned char>
data;
555 std::vector<std::vector<Node>> queue;
556 queue.push_back(std::move(
subs));
558 auto flattening{std::move(queue.back())};
560 for (
Node& n : flattening) {
561 if (!n.subs.empty()) queue.push_back(std::move(n.subs));
563 }
while (!queue.empty());
570 auto upfn = [](
const Node&
node, std::span<Node> children) {
571 std::vector<Node> new_subs;
572 for (
auto& child : children) {
575 new_subs.push_back(std::move(child));
579 return TreeEval<Node>(upfn);
583 uint32_t
K()
const {
return k; }
584 const std::vector<Key>&
Keys()
const {
return keys; }
585 const std::vector<unsigned char>&
Data()
const {
return data; }
586 const std::vector<Node>&
Subs()
const {
return subs; }
610 :
fragment(nt),
k(val),
keys(key),
data(
std::move(arg)),
subs(
std::move(sub)),
m_script_ctx{script_ctx},
ops(
CalcOps()),
ss(
CalcStackSize()),
ws(
CalcWitnessSize()),
typ(
CalcType()),
scriptlen(
CalcScriptLen()) {}
616 for (
const auto& sub :
subs) {
617 subsize += sub.ScriptSize();
619 Type sub0type =
subs.size() > 0 ?
subs[0].GetType() :
""_mst;
646 template<
typename Result,
typename State,
typename DownFn,
typename UpFn>
656 StackElem(
const Node& node_,
size_t exp_,
State&& state_) :
657 node(node_), expanded(exp_), state(std::move(state_)) {}
660 std::vector<StackElem> stack;
663 std::vector<Result> results;
664 stack.emplace_back(*
this, 0, std::move(root_state));
682 while (stack.size()) {
683 const Node&
node = stack.back().node;
684 if (stack.back().expanded <
node.subs.size()) {
688 size_t child_index = stack.back().expanded++;
689 State child_state = downfn(stack.back().state,
node, child_index);
690 stack.emplace_back(
node.subs[child_index], 0, std::move(child_state));
695 std::optional<Result>
result{upfn(std::move(stack.back().state),
node,
696 std::span<Result>{results}.last(
node.subs.size()))};
700 results.erase(results.end() -
node.subs.size(), results.end());
701 results.push_back(std::move(*
result));
705 assert(results.size() >= 1);
707 return std::move(results[0]);
712 template<
typename Result,
typename UpFn>
715 struct DummyState {};
716 return TreeEvalMaybe<Result>(DummyState{},
717 [](DummyState,
const Node&, size_t) {
return DummyState{}; },
718 [&upfn](DummyState,
const Node&
node, std::span<Result>
subs) {
725 template<
typename Result,
typename State,
typename DownFn,
typename UpFn>
730 return std::move(*TreeEvalMaybe<Result>(std::move(root_state),
731 std::forward<DownFn>(downfn),
734 return std::optional<Result>(std::move(res));
741 template<
typename Result,
typename UpFn>
744 struct DummyState {};
745 return std::move(*TreeEvalMaybe<Result>(DummyState{},
746 [](DummyState,
const Node&, size_t) {
return DummyState{}; },
747 [&upfn](DummyState,
const Node&
node, std::span<Result>
subs) {
749 return std::optional<Result>(std::move(res));
757 std::vector<std::pair<const Node<Key>&,
const Node<Key>&>> queue;
758 queue.emplace_back(node1, node2);
759 while (!queue.empty()) {
760 const auto& [a, b] = queue.back();
762 if (std::tie(a.fragment, a.k, a.keys, a.data) < std::tie(b.fragment, b.k, b.keys, b.data))
return -1;
763 if (std::tie(b.fragment, b.k, b.keys, b.data) < std::tie(a.fragment, a.k, a.keys, a.data))
return 1;
764 if (a.subs.size() < b.subs.size())
return -1;
765 if (b.subs.size() < a.subs.size())
return 1;
766 size_t n = a.
subs.size();
767 for (
size_t i = 0; i < n; ++i) {
768 queue.emplace_back(a.subs[n - 1 - i], b.subs[n - 1 - i]);
776 using namespace internal;
779 std::vector<Type> sub_types;
781 for (
const auto& sub :
subs) sub_types.push_back(sub.GetType());
792 template<
typename Ctx>
811 switch (
node.fragment) {
825 if (
node.subs[0].GetType() <<
"x"_mst) {
828 return std::move(
subs[0]);
845 for (
const auto& key :
node.keys) {
853 for (
auto it =
node.keys.begin() + 1; it !=
node.keys.end(); ++it) {
860 for (
size_t i = 1; i <
subs.size(); ++i) {
868 return TreeEval<CScript>(
false, downfn, upfn);
871 template<
typename CTx>
872 std::optional<std::string>
ToString(
const CTx& ctx)
const {
877 template<
typename CTx>
878 std::optional<std::string>
ToString(
const CTx& ctx,
bool& has_priv_key)
const {
882 auto downfn = [](bool,
const Node&
node, size_t) {
891 auto toString = [&ctx, &has_priv_key](Key key) -> std::optional<std::string> {
892 bool fragment_has_priv_key{
false};
893 auto key_str{ctx.ToString(key, fragment_has_priv_key)};
894 if (key_str) has_priv_key = has_priv_key || fragment_has_priv_key;
900 auto upfn = [is_tapscript, &toString](
bool wrapped,
const Node&
node, std::span<std::string>
subs) -> std::optional<std::string> {
901 std::string
ret = wrapped ?
":" :
"";
903 switch (
node.fragment) {
909 auto key_str = toString(
node.subs[0].keys[0]);
910 if (!key_str)
return {};
911 return std::move(
ret) +
"pk(" + std::move(*key_str) +
")";
915 auto key_str = toString(
node.subs[0].keys[0]);
916 if (!key_str)
return {};
917 return std::move(
ret) +
"pkh(" + std::move(*key_str) +
")";
919 return "c" + std::move(
subs[0]);
934 switch (
node.fragment) {
936 auto key_str = toString(
node.keys[0]);
937 if (!key_str)
return {};
938 return std::move(
ret) +
"pk_k(" + std::move(*key_str) +
")";
941 auto key_str = toString(
node.keys[0]);
942 if (!key_str)
return {};
943 return std::move(
ret) +
"pk_h(" + std::move(*key_str) +
")";
962 return std::move(
ret) +
"andor(" + std::move(
subs[0]) +
"," + std::move(
subs[1]) +
"," + std::move(
subs[2]) +
")";
966 for (
const auto& key :
node.keys) {
967 auto key_str = toString(key);
968 if (!key_str)
return {};
969 str +=
"," + std::move(*key_str);
971 return std::move(str) +
")";
976 for (
const auto& key :
node.keys) {
977 auto key_str = toString(key);
978 if (!key_str)
return {};
979 str +=
"," + std::move(*key_str);
981 return std::move(str) +
")";
985 for (
auto& sub :
subs) {
986 str +=
"," + std::move(sub);
988 return std::move(str) +
")";
995 return TreeEvalMaybe<std::string>(
false, downfn, upfn);
1013 const auto count{1 +
subs[0].ops.count +
subs[1].ops.count};
1014 const auto sat{
subs[0].ops.sat +
subs[1].ops.sat};
1015 const auto dsat{
subs[0].ops.dsat +
subs[1].ops.dsat};
1016 return {
count, sat, dsat};
1019 const auto count{1 +
subs[0].ops.count +
subs[1].ops.count};
1021 const auto dsat{
subs[0].ops.dsat +
subs[1].ops.dsat};
1022 return {
count, sat, dsat};
1025 const auto count{3 +
subs[0].ops.count +
subs[1].ops.count};
1026 const auto sat{
subs[0].ops.sat | (
subs[1].ops.sat +
subs[0].ops.dsat)};
1027 const auto dsat{
subs[0].ops.dsat +
subs[1].ops.dsat};
1028 return {
count, sat, dsat};
1031 const auto count{2 +
subs[0].ops.count +
subs[1].ops.count};
1032 const auto sat{
subs[0].ops.sat | (
subs[1].ops.sat +
subs[0].ops.dsat)};
1033 return {
count, sat, {}};
1036 const auto count{3 +
subs[0].ops.count +
subs[1].ops.count};
1037 const auto sat{
subs[0].ops.sat |
subs[1].ops.sat};
1038 const auto dsat{
subs[0].ops.dsat |
subs[1].ops.dsat};
1039 return {
count, sat, dsat};
1042 const auto count{3 +
subs[0].ops.count +
subs[1].ops.count +
subs[2].ops.count};
1044 const auto dsat{
subs[0].ops.dsat +
subs[2].ops.dsat};
1045 return {
count, sat, dsat};
1059 for (
const auto& sub :
subs) {
1060 count += sub.ops.count + 1;
1061 auto next_sats =
Vector(sats[0] + sub.ops.dsat);
1062 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub.ops.dsat) | (sats[j - 1] + sub.ops.sat));
1063 next_sats.push_back(sats[sats.size() - 1] + sub.ops.sat);
1064 sats = std::move(next_sats);
1067 return {
count, sats[
k], sats[0]};
1074 using namespace internal;
1090 const auto& x{
subs[0].ss};
1091 const auto& y{
subs[1].ss};
1092 const auto& z{
subs[2].ss};
1094 (x.Sat() + SatInfo::If() + y.Sat()) | (x.Dsat() + SatInfo::If() + z.Sat()),
1095 x.Dsat() + SatInfo::If() + z.Dsat()
1099 const auto& x{
subs[0].ss};
1100 const auto& y{
subs[1].ss};
1101 return {x.Sat() + y.Sat(), {}};
1104 const auto& x{
subs[0].ss};
1105 const auto& y{
subs[1].ss};
1106 return {x.Sat() + y.Sat() + SatInfo::BinaryOp(), x.Dsat() + y.Dsat() + SatInfo::BinaryOp()};
1109 const auto& x{
subs[0].ss};
1110 const auto& y{
subs[1].ss};
1112 ((x.Sat() + y.Dsat()) | (x.Dsat() + y.Sat())) + SatInfo::BinaryOp(),
1113 x.Dsat() + y.Dsat() + SatInfo::BinaryOp()
1117 const auto& x{
subs[0].ss};
1118 const auto& y{
subs[1].ss};
1119 return {(x.Sat() + SatInfo::If()) | (x.Dsat() + SatInfo::If() + y.Sat()), {}};
1122 const auto& x{
subs[0].ss};
1123 const auto& y{
subs[1].ss};
1130 const auto& x{
subs[0].ss};
1131 const auto& y{
subs[1].ss};
1132 return {SatInfo::If() + (x.Sat() | y.Sat()), SatInfo::If() + (x.Dsat() | y.Dsat())};
1161 auto sats =
Vector(SatInfo::Empty());
1162 for (
size_t i = 0; i <
subs.size(); ++i) {
1165 auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty();
1169 for (
size_t j = 1; j < sats.size(); ++j) {
1170 next_sats.push_back(((sats[j] +
subs[i].
ss.
Dsat()) | (sats[j - 1] +
subs[i].
ss.
Sat())) + add);
1173 next_sats.push_back(sats[sats.size() - 1] +
subs[i].ss.Sat() + add);
1175 sats = std::move(next_sats);
1204 const auto dsat{
subs[0].ws.dsat +
subs[2].ws.dsat};
1211 const auto dsat{
subs[0].ws.dsat +
subs[1].ws.dsat};
1228 for (
const auto& sub :
subs) {
1229 auto next_sats =
Vector(sats[0] + sub.ws.dsat);
1230 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub.ws.dsat) | (sats[j - 1] + sub.ws.sat));
1231 next_sats.push_back(sats[sats.size() - 1] + sub.ws.sat);
1232 sats = std::move(next_sats);
1235 return {sats[
k], sats[0]};
1241 template<
typename Ctx>
1243 using namespace internal;
1247 auto helper = [&ctx](
const Node&
node, std::span<InputResult> subres) -> InputResult {
1248 switch (
node.fragment) {
1250 std::vector<unsigned char> sig;
1252 return {
ZERO, InputStack(std::move(sig)).SetWithSig().SetAvailable(avail)};
1255 std::vector<unsigned char> key = ctx.ToPKBytes(
node.keys[0]), sig;
1257 return {
ZERO + InputStack(key), (InputStack(std::move(sig)).SetWithSig() + InputStack(key)).SetAvailable(avail)};
1263 for (
size_t i = 0; i <
node.keys.size(); ++i) {
1266 std::vector<unsigned char> sig;
1269 auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);
1273 std::vector<InputStack> next_sats;
1274 next_sats.push_back(sats[0] +
ZERO);
1275 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] +
ZERO) | (std::move(sats[j - 1]) + sat));
1276 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));
1278 sats = std::move(next_sats);
1282 auto& nsat{sats[0]};
1285 return {std::move(nsat), std::move(sats[
node.k])};
1292 for (
size_t i = 0; i <
node.keys.size(); ++i) {
1293 std::vector<unsigned char> sig;
1296 auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);
1300 std::vector<InputStack> next_sats;
1301 next_sats.push_back(sats[0]);
1302 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back(sats[j] | (std::move(sats[j - 1]) + sat));
1303 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));
1305 sats = std::move(next_sats);
1308 InputStack nsat =
ZERO;
1309 for (
size_t i = 0; i <
node.k; ++i) nsat = std::move(nsat) +
ZERO;
1311 return {std::move(nsat), std::move(sats[
node.k])};
1318 for (
size_t i = 0; i < subres.size(); ++i) {
1320 auto& res = subres[subres.size() - i - 1];
1324 std::vector<InputStack> next_sats;
1325 next_sats.push_back(sats[0] + res.nsat);
1326 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + res.nsat) | (std::move(sats[j - 1]) + res.sat));
1327 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(res.sat));
1329 sats = std::move(next_sats);
1333 InputStack nsat = INVALID;
1334 for (
size_t i = 0; i < sats.size(); ++i) {
1341 if (i != 0 && i !=
node.k) sats[i].SetMalleable().SetNonCanon();
1343 if (i !=
node.k) nsat = std::move(nsat) | std::move(sats[i]);
1346 return {std::move(nsat), std::move(sats[
node.k])};
1349 return {INVALID, ctx.CheckOlder(
node.k) ?
EMPTY : INVALID};
1352 return {INVALID, ctx.CheckAfter(
node.k) ?
EMPTY : INVALID};
1355 std::vector<unsigned char> preimage;
1357 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1360 std::vector<unsigned char> preimage;
1362 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1365 std::vector<unsigned char> preimage;
1367 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1370 std::vector<unsigned char> preimage;
1372 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1375 auto& x = subres[0], &y = subres[1];
1382 return {(y.nsat + x.sat).SetNonCanon(), y.sat + x.sat};
1385 auto& x = subres[0], &y = subres[1];
1391 return {(y.nsat + x.nsat) | (y.sat + x.nsat).SetMalleable().SetNonCanon() | (y.nsat + x.sat).SetMalleable().SetNonCanon(), y.sat + x.sat};
1394 auto& x = subres[0], &z = subres[1];
1396 return {z.nsat + x.nsat, (z.nsat + x.sat) | (z.sat + x.nsat) | (z.sat + x.sat).SetMalleable().SetNonCanon()};
1399 auto& x = subres[0], &z = subres[1];
1400 return {INVALID, std::move(x.sat) | (z.sat + x.nsat)};
1403 auto& x = subres[0], &z = subres[1];
1404 return {z.nsat + x.nsat, std::move(x.sat) | (z.sat + x.nsat)};
1407 auto& x = subres[0], &z = subres[1];
1408 return {(x.nsat + ONE) | (z.nsat +
ZERO), (x.sat + ONE) | (z.sat +
ZERO)};
1411 auto& x = subres[0], &y = subres[1], &z = subres[2];
1412 return {(y.nsat + x.sat).SetNonCanon() | (z.nsat + x.nsat), (y.sat + x.sat) | (z.sat + x.nsat)};
1418 return std::move(subres[0]);
1420 auto &x = subres[0];
1421 return {
ZERO, x.sat + ONE};
1424 auto &x = subres[0];
1430 return {InputStack(
ZERO).SetMalleable(x.nsat.available !=
Availability::NO && !x.nsat.has_sig), std::move(x.sat)};
1433 auto &x = subres[0];
1434 return {INVALID, std::move(x.sat)};
1440 return {INVALID, INVALID};
1443 auto tester = [&helper](
const Node&
node, std::span<InputResult> subres) -> InputResult {
1444 auto ret = helper(
node, subres);
1486 return TreeEval<InputResult>(tester);
1501 Comp(
const Ctx& ctx) : ctx_ptr(&ctx) {}
1502 bool operator()(
const Key& a,
const Key& b)
const {
return ctx_ptr->KeyCompare(a, b); }
1508 using keyset = std::set<Key, Comp>;
1509 using state = std::optional<keyset>;
1511 auto upfn = [&ctx](
const Node&
node, std::span<state>
subs) -> state {
1513 if (
node.has_duplicate_keys.has_value() && *
node.has_duplicate_keys)
return {};
1516 for (
auto& sub :
subs) {
1517 if (!sub.has_value()) {
1518 node.has_duplicate_keys =
true;
1525 size_t keys_count =
node.keys.size();
1526 keyset key_set{
node.keys.begin(),
node.keys.end(), Comp(ctx)};
1527 if (key_set.size() != keys_count) {
1529 node.has_duplicate_keys =
true;
1534 for (
auto& sub :
subs) {
1535 keys_count += sub->size();
1538 if (key_set.size() < sub->size()) std::swap(key_set, *sub);
1539 key_set.merge(*sub);
1540 if (key_set.size() != keys_count) {
1541 node.has_duplicate_keys =
true;
1546 node.has_duplicate_keys =
false;
1550 TreeEval<state>(upfn);
1574 return !((
GetType() &
"BKW"_mst) ==
""_mst);
1619 return TreeEval<const Node*>([](
const Node&
node, std::span<const Node*>
subs) ->
const Node* {
1620 for (
auto& sub:
subs)
if (sub)
return sub;
1621 if (!
node.IsSaneSubexpression())
return &
node;
1628 template<
typename F>
1632 return TreeEval<int>([&fn](
const Node&
node, std::span<int>
subs) ->
bool {
1633 switch (
node.fragment) {
1648 return bool{fn(
node)};
1671 if (
GetType() ==
""_mst)
return false;
1703 template<
typename Ctx>
1704 Availability Satisfy(
const Ctx& ctx, std::vector<std::vector<unsigned char>>& stack,
bool nonmalleable =
true)
const {
1707 stack = std::move(
ret.sat.stack);
1708 return ret.sat.available;
1729 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, std::vector<Node> sub, std::vector<unsigned char> arg, uint32_t val = 0)
1730 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) {
DuplicateKeyCheck(ctx); }
1731 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
1733 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, std::vector<Node> sub, std::vector<Key> key, uint32_t val = 0)
1734 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) {
DuplicateKeyCheck(ctx); }
1735 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, std::vector<Key> key, uint32_t val = 0)
1736 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) {
DuplicateKeyCheck(ctx); }
1737 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, std::vector<Node> sub, uint32_t val = 0)
1738 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) {
DuplicateKeyCheck(ctx); }
1739 template <
typename Ctx>
Node(
const Ctx& ctx,
enum Fragment nt, uint32_t val = 0)
1748 Node& operator=(
Node&&) noexcept = default;
1751 namespace internal {
1810 template<
typename Key,
typename Ctx>
1811 std::optional<Key>
ParseKey(
const std::string& func, std::span<const char>& in,
const Ctx& ctx)
1815 return ctx.FromString(expr);
1819 template<
typename Ctx>
1820 std::optional<std::vector<unsigned char>>
ParseHexStr(
const std::string& func, std::span<const char>& in,
const size_t expected_size,
1825 std::string val = std::string(expr.begin(), expr.end());
1826 if (!
IsHex(val))
return {};
1828 if (hash.size() != expected_size)
return {};
1833 template<
typename Key>
1836 Node<Key> child{std::move(constructed.back())};
1837 constructed.pop_back();
1850 template <
typename Key,
typename Ctx>
1851 inline std::optional<Node<Key>>
Parse(std::span<const char> in,
const Ctx& ctx)
1865 size_t script_size{1};
1869 std::vector<std::tuple<ParseContext, int64_t, int64_t>> to_parse;
1870 std::vector<Node<Key>> constructed;
1872 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1875 const auto parse_multi_exp = [&](std::span<const char>& in,
const bool is_multi_a) ->
bool {
1878 if (ctx.MsContext() != required_ctx)
return false;
1881 if (next_comma < 1)
return false;
1882 const auto k_to_integral{ToIntegral<int64_t>(std::string_view(in.data(), next_comma))};
1883 if (!k_to_integral.has_value())
return false;
1884 const int64_t
k{k_to_integral.value()};
1885 in = in.subspan(next_comma + 1);
1887 std::vector<Key>
keys;
1888 while (next_comma != -1) {
1890 int key_length = (next_comma == -1) ?
FindNextChar(in,
')') : next_comma;
1891 if (key_length < 1)
return false;
1892 std::span<const char> sp{in.begin(), in.begin() + key_length};
1893 auto key = ctx.FromString(sp);
1894 if (!key)
return false;
1895 keys.push_back(std::move(*key));
1896 in = in.subspan(key_length + 1);
1898 if (
keys.size() < 1 ||
keys.size() > max_keys)
return false;
1899 if (k < 1 || k > (int64_t)
keys.size())
return false;
1905 script_size += 2 + (
keys.size() > 16) + (
k > 16) + 34 *
keys.size();
1911 while (!to_parse.empty()) {
1912 if (script_size > max_size)
return {};
1915 auto [cur_context, n,
k] = to_parse.back();
1916 to_parse.pop_back();
1918 switch (cur_context) {
1919 case ParseContext::WRAPPED_EXPR: {
1920 std::optional<size_t> colon_index{};
1921 for (
size_t i = 1; i < in.size(); ++i) {
1926 if (in[i] <
'a' || in[i] >
'z')
break;
1929 bool last_was_v{
false};
1930 for (
size_t j = 0; colon_index && j < *colon_index; ++j) {
1931 if (script_size > max_size)
return {};
1934 to_parse.emplace_back(ParseContext::ALT, -1, -1);
1935 }
else if (in[j] ==
's') {
1937 to_parse.emplace_back(ParseContext::SWAP, -1, -1);
1938 }
else if (in[j] ==
'c') {
1941 }
else if (in[j] ==
'd') {
1943 to_parse.emplace_back(ParseContext::DUP_IF, -1, -1);
1944 }
else if (in[j] ==
'j') {
1946 to_parse.emplace_back(ParseContext::NON_ZERO, -1, -1);
1947 }
else if (in[j] ==
'n') {
1949 to_parse.emplace_back(ParseContext::ZERO_NOTEQUAL, -1, -1);
1950 }
else if (in[j] ==
'v') {
1953 if (last_was_v)
return {};
1954 to_parse.emplace_back(ParseContext::VERIFY, -1, -1);
1955 }
else if (in[j] ==
'u') {
1957 to_parse.emplace_back(ParseContext::WRAP_U, -1, -1);
1958 }
else if (in[j] ==
't') {
1960 to_parse.emplace_back(ParseContext::WRAP_T, -1, -1);
1961 }
else if (in[j] ==
'l') {
1969 last_was_v = (in[j] ==
'v');
1971 to_parse.emplace_back(ParseContext::EXPR, -1, -1);
1972 if (colon_index) in = in.subspan(*colon_index + 1);
1975 case ParseContext::EXPR: {
1976 if (
Const(
"0", in)) {
1978 }
else if (
Const(
"1", in)) {
1980 }
else if (
Const(
"pk(", in,
false)) {
1981 std::optional<Key> key = ParseKey<Key, Ctx>(
"pk", in, ctx);
1982 if (!key)
return {};
1984 script_size +=
IsTapscript(ctx.MsContext()) ? 33 : 34;
1985 }
else if (
Const(
"pkh(", in,
false)) {
1986 std::optional<Key> key = ParseKey<Key, Ctx>(
"pkh", in, ctx);
1987 if (!key)
return {};
1990 }
else if (
Const(
"pk_k(", in,
false)) {
1991 std::optional<Key> key = ParseKey<Key, Ctx>(
"pk_k", in, ctx);
1992 if (!key)
return {};
1994 script_size +=
IsTapscript(ctx.MsContext()) ? 32 : 33;
1995 }
else if (
Const(
"pk_h(", in,
false)) {
1996 std::optional<Key> key = ParseKey<Key, Ctx>(
"pk_h", in, ctx);
1997 if (!key)
return {};
2000 }
else if (
Const(
"sha256(", in,
false)) {
2001 std::optional<std::vector<unsigned char>> hash =
ParseHexStr(
"sha256", in, 32, ctx);
2002 if (!hash)
return {};
2005 }
else if (
Const(
"ripemd160(", in,
false)) {
2006 std::optional<std::vector<unsigned char>> hash =
ParseHexStr(
"ripemd160", in, 20, ctx);
2007 if (!hash)
return {};
2010 }
else if (
Const(
"hash256(", in,
false)) {
2011 std::optional<std::vector<unsigned char>> hash =
ParseHexStr(
"hash256", in, 32, ctx);
2012 if (!hash)
return {};
2015 }
else if (
Const(
"hash160(", in,
false)) {
2016 std::optional<std::vector<unsigned char>> hash =
ParseHexStr(
"hash160", in, 20, ctx);
2017 if (!hash)
return {};
2020 }
else if (
Const(
"after(", in,
false)) {
2021 auto expr =
Expr(in);
2022 if (!
Func(
"after", expr))
return {};
2023 const auto num{ToIntegral<int64_t>(std::string_view(expr.begin(), expr.end()))};
2024 if (!num.has_value() || *num < 1 || *num >= 0x80000000L)
return {};
2026 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
2027 }
else if (
Const(
"older(", in,
false)) {
2028 auto expr =
Expr(in);
2029 if (!
Func(
"older", expr))
return {};
2030 const auto num{ToIntegral<int64_t>(std::string_view(expr.begin(), expr.end()))};
2031 if (!num.has_value() || *num < 1 || *num >= 0x80000000L)
return {};
2033 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
2034 }
else if (
Const(
"multi(", in)) {
2035 if (!parse_multi_exp(in,
false))
return {};
2036 }
else if (
Const(
"multi_a(", in)) {
2037 if (!parse_multi_exp(in,
true))
return {};
2038 }
else if (
Const(
"thresh(", in)) {
2040 if (next_comma < 1)
return {};
2041 const auto k{ToIntegral<int64_t>(std::string_view(in.data(), next_comma))};
2042 if (!
k.has_value() || *
k < 1)
return {};
2043 in = in.subspan(next_comma + 1);
2046 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2047 script_size += 2 + (*
k > 16) + (*
k > 0x7f) + (*
k > 0x7fff) + (*
k > 0x7fffff);
2048 }
else if (
Const(
"andor(", in)) {
2050 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1);
2051 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2052 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
2053 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2054 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
2055 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2058 if (
Const(
"and_n(", in)) {
2059 to_parse.emplace_back(ParseContext::AND_N, -1, -1);
2061 }
else if (
Const(
"and_b(", in)) {
2064 }
else if (
Const(
"and_v(", in)) {
2067 }
else if (
Const(
"or_b(", in)) {
2070 }
else if (
Const(
"or_c(", in)) {
2073 }
else if (
Const(
"or_d(", in)) {
2076 }
else if (
Const(
"or_i(", in)) {
2082 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1);
2083 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2084 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
2085 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2089 case ParseContext::ALT: {
2093 case ParseContext::SWAP: {
2101 case ParseContext::DUP_IF: {
2105 case ParseContext::NON_ZERO: {
2109 case ParseContext::ZERO_NOTEQUAL: {
2113 case ParseContext::VERIFY: {
2114 script_size += (constructed.back().GetType() <<
"x"_mst);
2118 case ParseContext::WRAP_U: {
2122 case ParseContext::WRAP_T: {
2130 case ParseContext::AND_N: {
2131 auto mid = std::move(constructed.back());
2132 constructed.pop_back();
2157 auto right = std::move(constructed.back());
2158 constructed.pop_back();
2159 auto mid = std::move(constructed.back());
2160 constructed.pop_back();
2165 if (in.size() < 1)
return {};
2169 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2171 }
else if (in[0] ==
')') {
2172 if (
k > n)
return {};
2175 std::vector<Node<Key>>
subs;
2176 for (
int i = 0; i < n; ++i) {
2177 subs.push_back(std::move(constructed.back()));
2178 constructed.pop_back();
2180 std::reverse(
subs.begin(),
subs.end());
2187 case ParseContext::COMMA: {
2188 if (in.size() < 1 || in[0] !=
',')
return {};
2192 case ParseContext::CLOSE_BRACKET: {
2193 if (in.size() < 1 || in[0] !=
')')
return {};
2201 assert(constructed.size() >= 1);
2204 if (in.size() > 0)
return {};
2205 Node<Key> tl_node{std::move(constructed.front())};
2292 template <
typename Key,
typename Ctx,
typename I>
2293 inline std::optional<Node<Key>>
DecodeScript(I& in, I last,
const Ctx& ctx)
2296 std::vector<std::tuple<DecodeContext, int64_t, int64_t>> to_parse;
2297 std::vector<Node<Key>> constructed;
2301 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2303 while (!to_parse.empty()) {
2305 if (!constructed.empty() && !constructed.back().IsValid())
return {};
2308 auto [cur_context, n,
k] = to_parse.back();
2309 to_parse.pop_back();
2311 switch(cur_context) {
2312 case DecodeContext::SINGLE_BKV_EXPR: {
2313 if (in >= last)
return {};
2316 if (in[0].first ==
OP_1) {
2321 if (in[0].first ==
OP_0) {
2327 if (in[0].second.size() == 33 || in[0].second.size() == 32) {
2328 auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());
2329 if (!key)
return {};
2335 auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end());
2336 if (!key)
return {};
2342 std::optional<int64_t> num;
2345 if (*num < 1 || *num > 0x7FFFFFFFL)
return {};
2351 if (num < 1 || num > 0x7FFFFFFFL)
return {};
2357 if (in[2].first ==
OP_SHA256 && in[1].second.size() == 32) {
2361 }
else if (in[2].first ==
OP_RIPEMD160 && in[1].second.size() == 20) {
2365 }
else if (in[2].first ==
OP_HASH256 && in[1].second.size() == 32) {
2369 }
else if (in[2].first ==
OP_HASH160 && in[1].second.size() == 20) {
2378 std::vector<Key>
keys;
2380 if (!n || last - in < 3 + *n)
return {};
2381 if (*n < 1 || *n > 20)
return {};
2382 for (
int i = 0; i < *n; ++i) {
2383 if (in[2 + i].second.size() != 33)
return {};
2384 auto key = ctx.FromPKBytes(in[2 + i].second.begin(), in[2 + i].second.end());
2385 if (!key)
return {};
2386 keys.push_back(std::move(*key));
2389 if (!
k || *k < 1 || *k > *n)
return {};
2391 std::reverse(
keys.begin(),
keys.end());
2396 if (last - in >= 4 && in[0].first ==
OP_NUMEQUAL) {
2402 if (last - in < 2 + *
k * 2)
return {};
2403 std::vector<Key>
keys;
2406 for (
int pos = 2;; pos += 2) {
2407 if (last - in < pos + 2)
return {};
2410 if (in[pos + 1].second.size() != 32)
return {};
2411 auto key = ctx.FromPKBytes(in[pos + 1].second.begin(), in[pos + 1].second.end());
2412 if (!key)
return {};
2413 keys.push_back(std::move(*key));
2419 if (
keys.size() < (size_t)*
k)
return {};
2420 in += 2 +
keys.size() * 2;
2421 std::reverse(
keys.begin(),
keys.end());
2432 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2438 to_parse.emplace_back(DecodeContext::VERIFY, -1, -1);
2439 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2445 to_parse.emplace_back(DecodeContext::ZERO_NOTEQUAL, -1, -1);
2446 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2451 if (*num < 1)
return {};
2453 to_parse.emplace_back(DecodeContext::THRESH_W, 0, *num);
2459 to_parse.emplace_back(DecodeContext::ENDIF, -1, -1);
2460 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2472 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2473 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2480 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2481 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2487 case DecodeContext::BKV_EXPR: {
2488 to_parse.emplace_back(DecodeContext::MAYBE_AND_V, -1, -1);
2489 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2492 case DecodeContext::W_EXPR: {
2494 if (in >= last)
return {};
2497 to_parse.emplace_back(DecodeContext::ALT, -1, -1);
2499 to_parse.emplace_back(DecodeContext::SWAP, -1, -1);
2501 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2504 case DecodeContext::MAYBE_AND_V: {
2510 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2514 case DecodeContext::SWAP: {
2515 if (in >= last || in[0].first !=
OP_SWAP || constructed.empty())
return {};
2520 case DecodeContext::ALT: {
2521 if (in >= last || in[0].first !=
OP_TOALTSTACK || constructed.empty())
return {};
2527 if (constructed.empty())
return {};
2531 case DecodeContext::DUP_IF: {
2532 if (constructed.empty())
return {};
2536 case DecodeContext::VERIFY: {
2537 if (constructed.empty())
return {};
2541 case DecodeContext::NON_ZERO: {
2542 if (constructed.empty())
return {};
2546 case DecodeContext::ZERO_NOTEQUAL: {
2547 if (constructed.empty())
return {};
2552 if (constructed.size() < 2)
return {};
2557 if (constructed.size() < 2)
return {};
2562 if (constructed.size() < 2)
return {};
2567 if (constructed.size() < 2)
return {};
2572 if (constructed.size() < 2)
return {};
2577 if (constructed.size() < 3)
return {};
2578 Node left{std::move(constructed.back())};
2579 constructed.pop_back();
2580 Node right{std::move(constructed.back())};
2581 constructed.pop_back();
2582 Node mid{std::move(constructed.back())};
2586 case DecodeContext::THRESH_W: {
2587 if (in >= last)
return {};
2588 if (in[0].first ==
OP_ADD) {
2590 to_parse.emplace_back(DecodeContext::THRESH_W, n+1,
k);
2591 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2593 to_parse.emplace_back(DecodeContext::THRESH_E, n+1,
k);
2595 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2599 case DecodeContext::THRESH_E: {
2600 if (k < 1 || k > n || constructed.size() <
static_cast<size_t>(n))
return {};
2601 std::vector<Node<Key>>
subs;
2602 for (
int i = 0; i < n; ++i) {
2603 Node sub{std::move(constructed.back())};
2604 constructed.pop_back();
2605 subs.push_back(std::move(sub));
2610 case DecodeContext::ENDIF: {
2611 if (in >= last)
return {};
2616 to_parse.emplace_back(DecodeContext::ENDIF_ELSE, -1, -1);
2617 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2620 else if (in[0].first ==
OP_IF) {
2621 if (last - in >= 2 && in[1].first ==
OP_DUP) {
2623 to_parse.emplace_back(DecodeContext::DUP_IF, -1, -1);
2626 to_parse.emplace_back(DecodeContext::NON_ZERO, -1, -1);
2632 }
else if (in[0].first ==
OP_NOTIF) {
2634 to_parse.emplace_back(DecodeContext::ENDIF_NOTIF, -1, -1);
2641 case DecodeContext::ENDIF_NOTIF: {
2642 if (in >= last)
return {};
2650 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2653 case DecodeContext::ENDIF_ELSE: {
2654 if (in >= last)
return {};
2655 if (in[0].first ==
OP_IF) {
2658 }
else if (in[0].first ==
OP_NOTIF) {
2662 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2670 if (constructed.size() != 1)
return {};
2671 Node tl_node{std::move(constructed.front())};
2675 if (!tl_node.IsValidTopLevel())
return {};
2681 template <
typename Ctx>
2682 inline std::optional<Node<typename Ctx::Key>>
FromString(
const std::string& str,
const Ctx& ctx)
2684 return internal::Parse<typename Ctx::Key>(str, ctx);
2687 template <
typename Ctx>
2690 using namespace internal;
2694 if (!decomposed)
return {};
2695 auto it = decomposed->begin();
2696 auto ret = DecodeScript<typename Ctx::Key>(it, decomposed->end(), ctx);
2697 if (!
ret)
return {};
2698 if (it != decomposed->end())
return {};
2704 #endif // BITCOIN_SCRIPT_MINISCRIPT_H CScript BuildScript(Ts &&... inputs)
Build a script by concatenating other scripts, or any argument accepted by CScript::operator<<.
OP_SIZE 32 OP_EQUALVERIFY OP_HASH160 [hash] OP_EQUAL.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< unsigned char > arg, uint32_t val=0)
Potentially multiple SINGLE_BKV_EXPRs as children of (potentially multiple) and_v expressions...
[X] OP_VERIFY (or -VERIFY version of last opcode in X)
SWAP wraps the top constructed node with s:
std::optional< uint32_t > GetOps() const
Return the maximum number of ops needed to satisfy this script non-malleably.
[X] OP_NOTIF [Z] OP_ELSE [Y] OP_ENDIF
static const auto ZERO32
A stack consisting of a single malleable 32-byte 0x0000...0000 element (for dissatisfying hash challe...
enum Fragment Fragment() const
std::span< const char > Expr(std::span< const char > &sp)
Extract the expression that sp begins with.
Type CalcType() const
Compute the type for this miniscript.
static constexpr SatInfo Empty() noexcept
The empty script.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
static const int WITNESS_SCALE_FACTOR
size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx)
Helper function for Node::CalcScriptLen.
OP_DUP OP_HASH160 [keyhash] OP_EQUALVERIFY.
friend MaxInt< I > operator|(const MaxInt< I > &a, const MaxInt< I > &b)
ALT wraps the top constructed node with a:
constexpr uint32_t TXIN_BYTES_NO_WITNESS
prevout + nSequence + scriptSig
Type GetType() const
Return the expression type.
VERIFY wraps the top constructed node with v:
OP_SIZE 32 OP_EQUALVERIFY OP_RIPEMD160 [hash] OP_EQUAL.
static constexpr SatInfo OP_IFDUP(bool nonzero) noexcept
bool IsSaneSubexpression() const
Whether the apparent policy of this node matches its script semantics. Doesn't guarantee it is a safe...
[k] [key_n]* [n] OP_CHECKMULTISIG (only available within P2WSH context)
[n] OP_CHECKLOCKTIMEVERIFY
std::optional< uint32_t > GetExecStackSize() const
Return the maximum size of the stack during execution of this script.
uint32_t GetStaticOps() const
Return the number of ops in the script (not counting the dynamic ones that depend on execution)...
bool IsSatisfiable(F fn) const
Determine whether a Miniscript node is satisfiable.
int FindNextChar(std::span< const char > sp, const char m)
bool Const(const std::string &str, std::span< const char > &sp, bool skip)
Parse a constant.
bool valid
Whether a canonical satisfaction/dissatisfaction is possible at all.
std::optional< Result > TreeEvalMaybe(State root_state, DownFn downfn, UpFn upfn) const
OP_TOALTSTACK [X] OP_FROMALTSTACK.
const std::vector< Key > & Keys() const
internal::StackSize ss
Cached stack size bounds.
#define CHECK_NONFATAL(condition)
Identity function.
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
bool IsHex(std::string_view str)
Availability Satisfy(const Ctx &ctx, std::vector< std::vector< unsigned char >> &stack, bool nonmalleable=true) const
Produce a witness for this script, if possible and given the information available in the context...
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< Node > sub, std::vector< Key > key, std::vector< unsigned char > arg, uint32_t val)
static constexpr SatInfo OP_DUP() noexcept
If, inside an ENDIF context, we find an OP_NOTIF before finding an OP_ELSE, we could either be in an ...
internal::StackSize CalcStackSize() const
std::optional< std::string > ToString(const CTx &ctx, bool &has_priv_key) const
static const auto ONE
A stack consisting of a single 0x01 element (interpreted as 1 by the script interpreted in numeric co...
WRAP_U will construct an or_i(X,0) node from the top constructed node.
Ops(uint32_t in_count, MaxInt< uint32_t > in_sat, MaxInt< uint32_t > in_dsat)
ZERO_NOTEQUAL wraps the top constructed node with n:
constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept
static constexpr SatInfo Hash() noexcept
A script consisting of a single hash opcode.
[X] OP_NOTIF [Y] OP_ENDIF
MiniscriptContext m_script_ctx
The Script context for this node. Either P2WSH or Tapscript.
Result TreeEval(UpFn upfn) const
Like TreeEval, but without downfn or State type.
WRAP_T will construct an and_v(X,1) node from the top constructed node.
MaxInt< uint32_t > dsat
Maximum witness size to dissatisfy;.
bool IsNonMalleable() const
Check whether this script can always be satisfied in a non-malleable way.
internal::WitnessSize CalcWitnessSize() const
MaxInt< uint32_t > sat
Maximum witness size to satisfy;.
ENDIF signals that we are inside some sort of OP_IF structure, which could be or_d, or_c, or_i, andor, d:, or j: wrapper, depending on what follows.
std::optional< bool > has_duplicate_keys
Whether a public key appears more than once in this node.
std::optional< Node< typename Ctx::Key > > FromString(const std::string &str, const Ctx &ctx)
constexpr Type If(bool x) const
The empty type if x is false, itself otherwise.
void DuplicateKeyCheck(const Ctx &ctx) const
Update duplicate key information in this Node.
AND_N will construct an andor(X,Y,0) node from the last two constructed nodes.
bool IsNotSatisfiable() const
Whether no satisfaction exists for this node.
[X] OP_IFDUP OP_NOTIF [Y] OP_ENDIF
An expression which may be begin with wrappers followed by a colon.
std::optional< uint32_t > GetWitnessSize() const
Return the maximum size in bytes of a witness to satisfy this script non-malleably.
State
The various states a (txhash,peer) pair can be in.
static const int MAX_PUBKEYS_PER_MULTISIG
CLOSE_BRACKET expects the next element to be ')' and fails if not.
bool NeedsSignature() const
Check whether this script always needs a signature.
std::pair< opcodetype, std::vector< unsigned char > > Opcode
Node(const Ctx &ctx, enum Fragment nt, std::vector< Node > sub, std::vector< Key > key, uint32_t val=0)
static constexpr SatInfo BinaryOp() noexcept
A script consisting of just a binary operator (OP_BOOLAND, OP_BOOLOR, OP_ADD).
[X1] ([Xn] OP_ADD)* [k] OP_EQUAL
bool Func(const std::string &str, std::span< const char > &sp)
Parse a function call.
Result TreeEval(State root_state, DownFn &&downfn, UpFn upfn) const
Like TreeEvalMaybe, but always produces a result.
uint32_t count
Non-push opcodes.
size_t CalcScriptLen() const
Compute the length of the script for this miniscript (including children).
bool IsBKW() const
Whether this node is of type B, K or W.
std::vector< unsigned char > data
The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD160).
constexpr bool operator==(Type x) const
Equality operator.
A single expression of type B, K, or V.
std::optional< std::string > ToString(const CTx &ctx) const
In a thresh expression, all sub-expressions other than the first are W-type, and end in OP_ADD...
uint32_t m_flags
Internal bitmap of properties (see ""_mst operator for details).
Type SanitizeType(Type e)
A helper sanitizer/checker for the output of CalcType.
std::optional< std::vector< Opcode > > DecomposeScript(const CScript &script)
Decode a script into opcode/push pairs.
MaxInt< uint32_t > dsat
Number of keys in possibly executed OP_CHECKMULTISIG(VERIFY)s to dissatisfy.
Node(const Ctx &ctx, enum Fragment nt, std::vector< Node > sub, uint32_t val=0)
A miniscript expression which does not begin with wrappers.
const SatInfo & Sat() const
Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector< Type > &sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx)
Helper function for Node::CalcType.
OP_IF [X] OP_ELSE [Y] OP_ENDIF.
static const auto EMPTY
The empty stack.
std::vector< Node > subs
Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH)
[n] OP_CHECKSEQUENCEVERIFY
constexpr Type(uint32_t flags)
Internal constructor used by the ""_mst operator.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< Node > sub, std::vector< Key > key, uint32_t val=0)
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< Node > sub, uint32_t val=0)
bool CheckDuplicateKey() const
Check whether there is no duplicate key across this fragment and all its sub-fragments.
Node(const Ctx &ctx, enum Fragment nt, uint32_t val=0)
bool CheckOpsLimit() const
Check the ops limit of this script against the consensus limit.
MAYBE_AND_V will check if the next part of the script could be a valid miniscript sub-expression...
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE
The maximum size in bytes of a standard witnessScript.
Node & operator=(const Node &)=delete
CScript ToScript(const Ctx &ctx) const
size_t ScriptSize() const
Return the size of the script for this expression (faster than ToScript().size()).
Type typ
Cached expression type (computed by CalcType and fed through SanitizeType).
size_t scriptlen
Cached script length (computed by CalcScriptLen).
std::optional< std::vector< unsigned char > > ParseHexStr(const std::string &func, std::span< const char > &in, const size_t expected_size, const Ctx &ctx)
Parse a hex string fully contained within a fragment with the name given by 'func'.
int32_t exec
How much higher the stack size can be during execution compared to at the end.
constexpr uint32_t P2WSH_TXOUT_BYTES
nValue + script len + OP_0 + pushdata 32.
std::vector< std::common_type_t< Args... > > Vector(Args &&... args)
Construct a vector with the specified elements.
static bool verify(const CScriptNum10 &bignum, const CScriptNum &scriptnum)
static constexpr unsigned int MAX_PUBKEYS_PER_MULTI_A
The limit of keys in OP_CHECKSIGADD-based scripts.
NON_ZERO wraps the top constructed node with j:
WitnessSize(MaxInt< uint32_t > in_sat, MaxInt< uint32_t > in_dsat)
OP_DUP OP_IF [X] OP_ENDIF.
constexpr Type operator &(Type x) const
Compute the type with the intersection of properties.
internal::InputResult ProduceInput(const Ctx &ctx) const
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, uint32_t val=0)
COMMA expects the next element to be ',' and fails if not.
void ForEachNode(const Node< Key > &root, Fn &&fn)
Unordered traversal of a miniscript node tree.
#define CHECK(cond)
Unconditional failure on condition failure.
MiniscriptContext GetMsCtx() const
Return the script context for this node.
Node< Key > Clone() const
static const auto ZERO
A stack consisting of a single zero-length element (interpreted as 0 by the script interpreter in num...
bool IsSane() const
Check whether this node is safe as a script on its own.
friend int Compare(const Node< Key > &node1, const Node< Key > &node2)
Compare two miniscript subtrees, using a non-recursive algorithm.
THRESH_E constructs a thresh node from the appropriate number of constructed children.
static constexpr size_t TAPROOT_CONTROL_MAX_SIZE
constexpr friend SatInfo operator|(const SatInfo &a, const SatInfo &b) noexcept
Script set union.
bool operator==(const Node< Key > &arg) const
Equality testing.
std::optional< Result > TreeEvalMaybe(UpFn upfn) const
Like TreeEvalMaybe, but without downfn or State type.
static constexpr SatInfo OP_SIZE() noexcept
constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept
Script set with a single script in it, with specified netdiff and exec.
MaxInt< uint32_t > sat
Number of keys in possibly executed OP_CHECKMULTISIG(VERIFY)s to satisfy.
std::optional< Key > ParseKey(const std::string &func, std::span< const char > &in, const Ctx &ctx)
Parse a key expression fully contained within a fragment with the name given by 'func'.
OP_SIZE OP_0NOTEQUAL OP_IF [X] OP_ENDIF.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< Node > sub, std::vector< unsigned char > arg, uint32_t val=0)
constexpr SatInfo() noexcept
Empty script set.
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
Node(const Ctx &ctx, enum Fragment nt, std::vector< Key > key, uint32_t val=0)
constexpr Type operator|(Type x) const
Compute the type with the union of properties.
constexpr StackSize(SatInfo in_both) noexcept
std::optional< Node< Key > > Parse(std::span< const char > in, const Ctx &ctx)
Parse a miniscript from its textual descriptor form.
const std::vector< unsigned char > & Data() const
std::optional< Node< typename Ctx::Key > > FromScript(const CScript &script, const Ctx &ctx)
friend MaxInt< I > operator+(const MaxInt< I > &a, const MaxInt< I > &b)
const SatInfo & Dsat() const
static constexpr SatInfo If() noexcept
A script consisting of just OP_IF or OP_NOTIF.
internal::Ops CalcOps() const
constexpr uint32_t MAX_TAPSCRIPT_SAT_SIZE
Maximum possible stack size to spend a Taproot output (excluding the script itself).
bool IsValid() const
Check whether this node is valid at all.
const std::vector< Node > & Subs() const
Serialized script, used inside transaction inputs and outputs.
static const int MAX_OPS_PER_SCRIPT
static constexpr SatInfo OP_EQUALVERIFY() noexcept
Fragment
The different node types in miniscript.
internal::WitnessSize ws
Cached witness size bounds.
static constexpr SatInfo Nop() noexcept
A script consisting of just a repurposed nop (OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY).
constexpr bool operator<<(Type x) const
Check whether the left hand's properties are superset of the right's (= left is a subtype of right)...
Node(const Ctx &ctx, enum Fragment nt, std::vector< Node > sub, std::vector< unsigned char > arg, uint32_t val=0)
static constexpr unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS
The maximum number of witness stack items in a standard P2WSH script.
static constexpr SatInfo OP_0NOTEQUAL() noexcept
std::optional< uint32_t > GetStackSize() const
Return the maximum number of stack elements needed to satisfy this script non-malleably.
const Node * FindInsaneSub() const
Find an insane subnode which has no insane children. Nullptr if there is none.
bool CheckTimeLocksMix() const
Check whether there is no satisfaction path that contains both timelocks and heightlocks.
enum Fragment fragment
What node type this node is.
DUP_IF wraps the top constructed node with d:
static constexpr SatInfo OP_VERIFY() noexcept
OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 [hash] OP_EQUAL.
An expression of type W (a: or s: wrappers).
uint32_t k
The k parameter (time for OLDER/AFTER, threshold for THRESH(_M))
std::optional< Node< Key > > DecodeScript(I &in, I last, const Ctx &ctx)
Parse a miniscript from a bitcoin script.
void BuildBack(const MiniscriptContext script_ctx, Fragment nt, std::vector< Node< Key >> &constructed, const bool reverse=false)
BuildBack pops the last two elements off constructed and wraps them in the specified Fragment...
constexpr bool operator<(Type x) const
Comparison operator to enable use in sets/maps (total ordering incompatible with <<).
A node in a miniscript expression.
Node(const Ctx &ctx, enum Fragment nt, std::vector< unsigned char > arg, uint32_t val=0)
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector< Key > key, uint32_t val=0)
OP_SIZE 32 OP_EQUALVERIFY OP_HASH256 [hash] OP_EQUAL.
[key_0] OP_CHECKSIG ([key_n] OP_CHECKSIGADD)* [k] OP_NUMEQUAL (only within Tapscript ctx) ...
static const std::vector< uint8_t > EMPTY
bool ValidSatisfactions() const
Whether successful non-malleable satisfactions are guaranteed to be valid.
constexpr uint32_t MaxScriptSize(MiniscriptContext ms_ctx)
The maximum size of a script depending on the context.
static constexpr SatInfo Push() noexcept
A script consisting of a single push opcode.
static const int MAX_STACK_SIZE
static constexpr SatInfo OP_EQUAL() noexcept
constexpr friend SatInfo operator+(const SatInfo &a, const SatInfo &b) noexcept
Script set concatenation.
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 ...
If, inside an ENDIF context, we find an OP_ELSE, then we could be in either an or_i or an andor node...
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
constexpr uint32_t TX_BODY_LEEWAY_WEIGHT
Data other than the witness in a transaction. Overhead + vin count + one vin + vout count + one vout ...
This type encapsulates the miniscript type system properties.
static constexpr SatInfo OP_CHECKSIG() noexcept
Class whose objects represent the maximum of a list of integers.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
bool CheckStackSize() const
Check the maximum stack size for this script against the policy limit.
static const auto INVALID
A stack representing the lack of any (dis)satisfactions.
std::vector< Key > keys
The keys used by this expression (only for PK_K/PK_H/MULTI)
static constexpr uint32_t MAX_TAPMINISCRIPT_STACK_ELEM_SIZE
The maximum size of a witness item for a Miniscript under Tapscript context. (A BIP340 signature with...
int32_t netdiff
How much higher the stack size at start of execution can be compared to at the end.
A data structure to help the calculation of stack size limits.
std::optional< int64_t > ParseScriptNumber(const Opcode &in)
Determine whether the passed pair (created by DecomposeScript) is pushing a number.
constexpr uint32_t TX_OVERHEAD
version + nLockTime
internal::Ops ops
Cached ops counts.
bool IsValidTopLevel() const
Check whether this node is valid as a script on its own.