5 #ifndef BITCOIN_SCRIPT_MINISCRIPT_H 6 #define BITCOIN_SCRIPT_MINISCRIPT_H 157 inline consteval
Type operator""_mst(
const char* c,
size_t l)
161 for (
const char *p = c; p < c + l; p++) {
173 *p ==
'f' ? 1 << 10 :
174 *p ==
's' ? 1 << 11 :
175 *p ==
'm' ? 1 << 12 :
176 *p ==
'x' ? 1 << 13 :
177 *p ==
'g' ? 1 << 14 :
178 *p ==
'h' ? 1 << 15 :
179 *p ==
'i' ? 1 << 16 :
180 *p ==
'j' ? 1 << 17 :
181 *p ==
'k' ? 1 << 18 :
182 (
throw std::logic_error(
"Unknown character in _mst literal"), 0)
189 using Opcode = std::pair<opcodetype, std::vector<unsigned char>>;
191 template<
typename Key>
struct Node;
192 template<
typename Key>
using NodeRef = std::shared_ptr<const Node<Key>>;
195 template<
typename Key,
typename... Args>
311 std::vector<std::vector<unsigned char>>
stack;
345 template<
typename A,
typename B>
364 if (!a.
valid)
return b;
365 if (!b.
valid)
return a;
434 constexpr
SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept :
441 if (!a.valid)
return b;
442 if (!b.valid)
return a;
444 return {std::max(a.netdiff, b.netdiff), std::max(a.exec, b.exec)};
451 if (!a.valid || !b.valid)
return {};
455 return {a.
netdiff + b.netdiff, std::max(b.exec, b.netdiff + a.exec)};
467 static constexpr
SatInfo If() noexcept {
return {1, 1}; }
473 static constexpr
SatInfo OP_IFDUP(
bool nonzero) noexcept {
return {nonzero ? -1 : 0, 0}; }
503 template<
typename Key>
508 const uint32_t
k = 0;
512 const std::vector<unsigned char>
data;
514 mutable std::vector<NodeRef<Key>>
subs;
521 while (!
subs.empty()) {
524 while (!
node->subs.empty()) {
525 subs.push_back(std::move(
node->subs.back()));
526 node->subs.pop_back();
553 for (
const auto& sub :
subs) {
554 subsize += sub->ScriptSize();
556 static constexpr
auto NONE_MST{
""_mst};
557 Type sub0type =
subs.size() > 0 ?
subs[0]->GetType() : NONE_MST;
584 template<
typename Result,
typename State,
typename DownFn,
typename UpFn>
594 StackElem(
const Node& node_,
size_t exp_,
State&& state_) :
595 node(node_), expanded(exp_), state(std::move(state_)) {}
598 std::vector<StackElem> stack;
601 std::vector<Result> results;
602 stack.emplace_back(*
this, 0, std::move(root_state));
620 while (stack.size()) {
621 const Node&
node = stack.back().node;
622 if (stack.back().expanded <
node.subs.size()) {
626 size_t child_index = stack.back().expanded++;
627 State child_state = downfn(stack.back().state,
node, child_index);
628 stack.emplace_back(*
node.subs[child_index], 0, std::move(child_state));
633 std::optional<Result> result{upfn(std::move(stack.back().state),
node,
636 if (!result)
return {};
638 results.erase(results.end() -
node.subs.size(), results.end());
639 results.push_back(std::move(*result));
643 assert(results.size() == 1);
644 return std::move(results[0]);
649 template<
typename Result,
typename UpFn>
652 struct DummyState {};
653 return TreeEvalMaybe<Result>(DummyState{},
654 [](DummyState,
const Node&, size_t) {
return DummyState{}; },
662 template<
typename Result,
typename State,
typename DownFn,
typename UpFn>
667 return std::move(*TreeEvalMaybe<Result>(std::move(root_state),
668 std::forward<DownFn>(downfn),
671 return std::optional<Result>(std::move(res));
678 template<
typename Result,
typename UpFn>
681 struct DummyState {};
682 return std::move(*TreeEvalMaybe<Result>(DummyState{},
683 [](DummyState,
const Node&, size_t) {
return DummyState{}; },
686 return std::optional<Result>(std::move(res));
694 std::vector<std::pair<const Node<Key>&,
const Node<Key>&>> queue;
695 queue.emplace_back(node1, node2);
696 while (!queue.empty()) {
697 const auto& [a, b] = queue.back();
699 if (std::tie(a.fragment, a.k, a.keys, a.data) < std::tie(b.fragment, b.k, b.keys, b.data))
return -1;
700 if (std::tie(b.fragment, b.k, b.keys, b.data) < std::tie(a.fragment, a.k, a.keys, a.data))
return 1;
701 if (a.subs.size() < b.subs.size())
return -1;
702 if (b.subs.size() < a.subs.size())
return 1;
703 size_t n = a.
subs.size();
704 for (
size_t i = 0; i < n; ++i) {
705 queue.emplace_back(*a.subs[n - 1 - i], *b.subs[n - 1 - i]);
713 using namespace internal;
716 std::vector<Type> sub_types;
718 for (
const auto& sub :
subs) sub_types.push_back(sub->GetType());
721 static constexpr
auto NONE_MST{
""_mst};
722 Type x =
subs.size() > 0 ?
subs[0]->GetType() : NONE_MST;
723 Type y =
subs.size() > 1 ?
subs[1]->GetType() : NONE_MST;
724 Type z =
subs.size() > 2 ?
subs[2]->GetType() : NONE_MST;
730 template<
typename Ctx>
749 switch (
node.fragment) {
763 if (
node.subs[0]->GetType() <<
"x"_mst) {
766 return std::move(
subs[0]);
783 for (
const auto& key :
node.keys) {
791 for (
auto it =
node.keys.begin() + 1; it !=
node.keys.end(); ++it) {
798 for (
size_t i = 1; i <
subs.size(); ++i) {
806 return TreeEval<CScript>(
false, downfn, upfn);
809 template<
typename CTx>
810 std::optional<std::string>
ToString(
const CTx& ctx)
const {
814 auto downfn = [](bool,
const Node&
node, size_t) {
827 std::string
ret = wrapped ?
":" :
"";
829 switch (
node.fragment) {
835 auto key_str = ctx.ToString(
node.subs[0]->keys[0]);
836 if (!key_str)
return {};
837 return std::move(
ret) +
"pk(" + std::move(*key_str) +
")";
841 auto key_str = ctx.ToString(
node.subs[0]->keys[0]);
842 if (!key_str)
return {};
843 return std::move(
ret) +
"pkh(" + std::move(*key_str) +
")";
845 return "c" + std::move(
subs[0]);
860 switch (
node.fragment) {
862 auto key_str = ctx.ToString(
node.keys[0]);
863 if (!key_str)
return {};
864 return std::move(
ret) +
"pk_k(" + std::move(*key_str) +
")";
867 auto key_str = ctx.ToString(
node.keys[0]);
868 if (!key_str)
return {};
869 return std::move(
ret) +
"pk_h(" + std::move(*key_str) +
")";
888 return std::move(
ret) +
"andor(" + std::move(
subs[0]) +
"," + std::move(
subs[1]) +
"," + std::move(
subs[2]) +
")";
892 for (
const auto& key :
node.keys) {
893 auto key_str = ctx.ToString(key);
894 if (!key_str)
return {};
895 str +=
"," + std::move(*key_str);
897 return std::move(str) +
")";
902 for (
const auto& key :
node.keys) {
903 auto key_str = ctx.ToString(key);
904 if (!key_str)
return {};
905 str +=
"," + std::move(*key_str);
907 return std::move(str) +
")";
911 for (
auto& sub :
subs) {
912 str +=
"," + std::move(sub);
914 return std::move(str) +
")";
921 return TreeEvalMaybe<std::string>(
false, downfn, upfn);
939 const auto count{1 +
subs[0]->ops.count +
subs[1]->ops.count};
940 const auto sat{
subs[0]->ops.sat +
subs[1]->ops.sat};
941 const auto dsat{
subs[0]->ops.dsat +
subs[1]->ops.dsat};
942 return {
count, sat, dsat};
945 const auto count{1 +
subs[0]->ops.count +
subs[1]->ops.count};
947 const auto dsat{
subs[0]->ops.dsat +
subs[1]->ops.dsat};
948 return {
count, sat, dsat};
951 const auto count{3 +
subs[0]->ops.count +
subs[1]->ops.count};
952 const auto sat{
subs[0]->ops.sat | (
subs[1]->ops.sat +
subs[0]->ops.dsat)};
953 const auto dsat{
subs[0]->ops.dsat +
subs[1]->ops.dsat};
954 return {
count, sat, dsat};
957 const auto count{2 +
subs[0]->ops.count +
subs[1]->ops.count};
958 const auto sat{
subs[0]->ops.sat | (
subs[1]->ops.sat +
subs[0]->ops.dsat)};
959 return {
count, sat, {}};
962 const auto count{3 +
subs[0]->ops.count +
subs[1]->ops.count};
963 const auto sat{
subs[0]->ops.sat |
subs[1]->ops.sat};
964 const auto dsat{
subs[0]->ops.dsat |
subs[1]->ops.dsat};
965 return {
count, sat, dsat};
968 const auto count{3 +
subs[0]->ops.count +
subs[1]->ops.count +
subs[2]->ops.count};
970 const auto dsat{
subs[0]->ops.dsat +
subs[2]->ops.dsat};
971 return {
count, sat, dsat};
985 for (
const auto& sub :
subs) {
986 count += sub->ops.count + 1;
987 auto next_sats =
Vector(sats[0] + sub->ops.dsat);
988 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub->ops.dsat) | (sats[j - 1] + sub->ops.sat));
989 next_sats.push_back(sats[sats.size() - 1] + sub->ops.sat);
990 sats = std::move(next_sats);
993 return {
count, sats[
k], sats[0]};
1000 using namespace internal;
1016 const auto& x{
subs[0]->ss};
1017 const auto& y{
subs[1]->ss};
1018 const auto& z{
subs[2]->ss};
1020 (x.sat + SatInfo::If() + y.sat) | (x.dsat + SatInfo::If() + z.sat),
1021 x.dsat + SatInfo::If() + z.dsat
1025 const auto& x{
subs[0]->ss};
1026 const auto& y{
subs[1]->ss};
1027 return {x.sat + y.sat, {}};
1030 const auto& x{
subs[0]->ss};
1031 const auto& y{
subs[1]->ss};
1032 return {x.sat + y.sat + SatInfo::BinaryOp(), x.dsat + y.dsat + SatInfo::BinaryOp()};
1035 const auto& x{
subs[0]->ss};
1036 const auto& y{
subs[1]->ss};
1038 ((x.sat + y.dsat) | (x.dsat + y.sat)) + SatInfo::BinaryOp(),
1039 x.dsat + y.dsat + SatInfo::BinaryOp()
1043 const auto& x{
subs[0]->ss};
1044 const auto& y{
subs[1]->ss};
1045 return {(x.sat + SatInfo::If()) | (x.dsat + SatInfo::If() + y.sat), {}};
1048 const auto& x{
subs[0]->ss};
1049 const auto& y{
subs[1]->ss};
1056 const auto& x{
subs[0]->ss};
1057 const auto& y{
subs[1]->ss};
1058 return {SatInfo::If() + (x.sat | y.sat), SatInfo::If() + (x.dsat | y.dsat)};
1087 auto sats =
Vector(SatInfo::Empty());
1088 for (
size_t i = 0; i <
subs.size(); ++i) {
1091 auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty();
1095 for (
size_t j = 1; j < sats.size(); ++j) {
1096 next_sats.push_back(((sats[j] +
subs[i]->
ss.
dsat) | (sats[j - 1] +
subs[i]->ss.sat)) + add);
1099 next_sats.push_back(sats[sats.size() - 1] +
subs[i]->ss.sat + add);
1101 sats = std::move(next_sats);
1130 const auto dsat{
subs[0]->ws.dsat +
subs[2]->ws.dsat};
1137 const auto dsat{
subs[0]->ws.dsat +
subs[1]->ws.dsat};
1154 for (
const auto& sub :
subs) {
1155 auto next_sats =
Vector(sats[0] + sub->ws.dsat);
1156 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub->ws.dsat) | (sats[j - 1] + sub->ws.sat));
1157 next_sats.push_back(sats[sats.size() - 1] + sub->ws.sat);
1158 sats = std::move(next_sats);
1161 return {sats[
k], sats[0]};
1167 template<
typename Ctx>
1169 using namespace internal;
1174 switch (
node.fragment) {
1176 std::vector<unsigned char> sig;
1178 return {
ZERO, InputStack(std::move(sig)).SetWithSig().SetAvailable(avail)};
1181 std::vector<unsigned char> key = ctx.ToPKBytes(
node.keys[0]), sig;
1183 return {
ZERO + InputStack(key), (InputStack(std::move(sig)).SetWithSig() + InputStack(key)).SetAvailable(avail)};
1189 for (
size_t i = 0; i <
node.keys.size(); ++i) {
1192 std::vector<unsigned char> sig;
1195 auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);
1199 std::vector<InputStack> next_sats;
1200 next_sats.push_back(sats[0] +
ZERO);
1201 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] +
ZERO) | (std::move(sats[j - 1]) + sat));
1202 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));
1204 sats = std::move(next_sats);
1208 auto& nsat{sats[0]};
1211 return {std::move(nsat), std::move(sats[
node.k])};
1218 for (
size_t i = 0; i <
node.keys.size(); ++i) {
1219 std::vector<unsigned char> sig;
1222 auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);
1226 std::vector<InputStack> next_sats;
1227 next_sats.push_back(sats[0]);
1228 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back(sats[j] | (std::move(sats[j - 1]) + sat));
1229 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));
1231 sats = std::move(next_sats);
1234 InputStack nsat =
ZERO;
1235 for (
size_t i = 0; i <
node.k; ++i) nsat = std::move(nsat) +
ZERO;
1237 return {std::move(nsat), std::move(sats[
node.k])};
1244 for (
size_t i = 0; i < subres.size(); ++i) {
1246 auto& res = subres[subres.size() - i - 1];
1250 std::vector<InputStack> next_sats;
1251 next_sats.push_back(sats[0] + res.nsat);
1252 for (
size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + res.nsat) | (std::move(sats[j - 1]) + res.sat));
1253 next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(res.sat));
1255 sats = std::move(next_sats);
1259 InputStack nsat = INVALID;
1260 for (
size_t i = 0; i < sats.size(); ++i) {
1267 if (i != 0 && i !=
node.k) sats[i].SetMalleable().SetNonCanon();
1269 if (i !=
node.k) nsat = std::move(nsat) | std::move(sats[i]);
1272 return {std::move(nsat), std::move(sats[
node.k])};
1275 return {INVALID, ctx.CheckOlder(
node.k) ?
EMPTY : INVALID};
1278 return {INVALID, ctx.CheckAfter(
node.k) ?
EMPTY : INVALID};
1281 std::vector<unsigned char> preimage;
1283 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1286 std::vector<unsigned char> preimage;
1288 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1291 std::vector<unsigned char> preimage;
1293 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1296 std::vector<unsigned char> preimage;
1298 return {
ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};
1301 auto& x = subres[0], &y = subres[1];
1308 return {(y.nsat + x.sat).SetNonCanon(), y.sat + x.sat};
1311 auto& x = subres[0], &y = subres[1];
1317 return {(y.nsat + x.nsat) | (y.sat + x.nsat).SetMalleable().SetNonCanon() | (y.nsat + x.sat).SetMalleable().SetNonCanon(), y.sat + x.sat};
1320 auto& x = subres[0], &z = subres[1];
1322 return {z.nsat + x.nsat, (z.nsat + x.sat) | (z.sat + x.nsat) | (z.sat + x.sat).SetMalleable().SetNonCanon()};
1325 auto& x = subres[0], &z = subres[1];
1326 return {INVALID, std::move(x.sat) | (z.sat + x.nsat)};
1329 auto& x = subres[0], &z = subres[1];
1330 return {z.nsat + x.nsat, std::move(x.sat) | (z.sat + x.nsat)};
1333 auto& x = subres[0], &z = subres[1];
1334 return {(x.nsat +
ONE) | (z.nsat +
ZERO), (x.sat +
ONE) | (z.sat +
ZERO)};
1337 auto& x = subres[0], &y = subres[1], &z = subres[2];
1338 return {(y.nsat + x.sat).SetNonCanon() | (z.nsat + x.nsat), (y.sat + x.sat) | (z.sat + x.nsat)};
1344 return std::move(subres[0]);
1346 auto &x = subres[0];
1350 auto &x = subres[0];
1356 return {InputStack(
ZERO).SetMalleable(x.nsat.available !=
Availability::NO && !x.nsat.has_sig), std::move(x.sat)};
1359 auto &x = subres[0];
1360 return {INVALID, std::move(x.sat)};
1366 return {INVALID, INVALID};
1370 auto ret = helper(
node, subres);
1393 if (
node.GetType() <<
"d"_mst && !
ret.nsat.malleable)
assert(!
ret.nsat.non_canon);
1401 if (
node.GetType() <<
"me"_mst)
assert(!
ret.nsat.malleable);
1412 return TreeEval<InputResult>(tester);
1427 Comp(
const Ctx& ctx) : ctx_ptr(&ctx) {}
1428 bool operator()(
const Key& a,
const Key& b)
const {
return ctx_ptr->KeyCompare(a, b); }
1434 using keyset = std::set<Key, Comp>;
1435 using state = std::optional<keyset>;
1439 if (
node.has_duplicate_keys.has_value() && *
node.has_duplicate_keys)
return {};
1442 for (
auto& sub :
subs) {
1443 if (!sub.has_value()) {
1444 node.has_duplicate_keys =
true;
1451 size_t keys_count =
node.keys.size();
1452 keyset key_set{
node.keys.begin(),
node.keys.end(), Comp(ctx)};
1453 if (key_set.size() != keys_count) {
1455 node.has_duplicate_keys =
true;
1460 for (
auto& sub :
subs) {
1461 keys_count += sub->size();
1464 if (key_set.size() < sub->size()) std::swap(key_set, *sub);
1465 key_set.merge(*sub);
1466 if (key_set.size() != keys_count) {
1467 node.has_duplicate_keys =
true;
1472 node.has_duplicate_keys =
false;
1476 TreeEval<state>(upfn);
1500 return !((
GetType() &
"BKW"_mst) ==
""_mst);
1546 for (
auto& sub:
subs)
if (sub)
return sub;
1547 if (!
node.IsSaneSubexpression())
return &
node;
1554 template<
typename F>
1559 switch (
node.fragment) {
1574 return bool{fn(
node)};
1596 if (
GetType() ==
""_mst)
return false;
1628 template<
typename Ctx>
1629 Availability Satisfy(
const Ctx& ctx, std::vector<std::vector<unsigned char>>& stack,
bool nonmalleable =
true)
const {
1632 stack = std::move(
ret.sat.stack);
1633 return ret.sat.available;
1654 template <
typename Ctx>
Node(
const Ctx& ctx,
Fragment nt, std::vector<
NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0)
1655 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) {
DuplicateKeyCheck(ctx); }
1656 template <
typename Ctx>
Node(
const Ctx& ctx,
Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
1659 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) {
DuplicateKeyCheck(ctx); }
1660 template <
typename Ctx>
Node(
const Ctx& ctx,
Fragment nt, std::vector<Key> key, uint32_t val = 0)
1661 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) {
DuplicateKeyCheck(ctx); }
1663 :
Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) {
DuplicateKeyCheck(ctx); }
1664 template <
typename Ctx>
Node(
const Ctx& ctx,
Fragment nt, uint32_t val = 0)
1668 namespace internal {
1727 template<
typename Key,
typename Ctx>
1731 if (key_size < 1)
return {};
1732 auto key = ctx.FromString(in.
begin(), in.
begin() + key_size);
1733 if (!key)
return {};
1734 return {{std::move(*key), key_size}};
1738 template<
typename Ctx>
1743 if (hash_size < 1)
return {};
1744 std::string val = std::string(in.
begin(), in.
begin() + hash_size);
1745 if (!
IsHex(val))
return {};
1747 if (hash.size() != expected_size)
return {};
1748 return {{std::move(hash), hash_size}};
1752 template<
typename Key>
1756 constructed.pop_back();
1758 constructed.back() = MakeNodeRef<Key>(
internal::NoDupCheck{}, script_ctx, nt,
Vector(std::move(child), std::move(constructed.back())));
1760 constructed.back() = MakeNodeRef<Key>(
internal::NoDupCheck{}, script_ctx, nt,
Vector(std::move(constructed.back()), std::move(child)));
1769 template<
typename Key,
typename Ctx>
1784 size_t script_size{1};
1788 std::vector<std::tuple<ParseContext, int64_t, int64_t>> to_parse;
1789 std::vector<NodeRef<Key>> constructed;
1791 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1794 const auto parse_multi_exp = [&](
Span<const char>& in,
const bool is_multi_a) ->
bool {
1797 if (ctx.MsContext() != required_ctx)
return false;
1800 if (next_comma < 1)
return false;
1801 const auto k_to_integral{ToIntegral<int64_t>(std::string_view(in.
begin(), next_comma))};
1802 if (!k_to_integral.has_value())
return false;
1803 const int64_t
k{k_to_integral.value()};
1804 in = in.
subspan(next_comma + 1);
1806 std::vector<Key>
keys;
1807 while (next_comma != -1) {
1809 int key_length = (next_comma == -1) ?
FindNextChar(in,
')') : next_comma;
1810 if (key_length < 1)
return false;
1811 auto key = ctx.FromString(in.
begin(), in.
begin() + key_length);
1812 if (!key)
return false;
1813 keys.push_back(std::move(*key));
1814 in = in.
subspan(key_length + 1);
1816 if (
keys.size() < 1 ||
keys.size() > max_keys)
return false;
1817 if (k < 1 || k > (int64_t)
keys.size())
return false;
1823 script_size += 2 + (
keys.size() > 16) + (
k > 16) + 34 *
keys.size();
1829 while (!to_parse.empty()) {
1830 if (script_size > max_size)
return {};
1833 auto [cur_context, n,
k] = to_parse.back();
1834 to_parse.pop_back();
1836 switch (cur_context) {
1837 case ParseContext::WRAPPED_EXPR: {
1838 std::optional<size_t> colon_index{};
1839 for (
size_t i = 1; i < in.
size(); ++i) {
1844 if (in[i] <
'a' || in[i] >
'z')
break;
1847 bool last_was_v{
false};
1848 for (
size_t j = 0; colon_index && j < *colon_index; ++j) {
1849 if (script_size > max_size)
return {};
1852 to_parse.emplace_back(ParseContext::ALT, -1, -1);
1853 }
else if (in[j] ==
's') {
1855 to_parse.emplace_back(ParseContext::SWAP, -1, -1);
1856 }
else if (in[j] ==
'c') {
1859 }
else if (in[j] ==
'd') {
1861 to_parse.emplace_back(ParseContext::DUP_IF, -1, -1);
1862 }
else if (in[j] ==
'j') {
1864 to_parse.emplace_back(ParseContext::NON_ZERO, -1, -1);
1865 }
else if (in[j] ==
'n') {
1867 to_parse.emplace_back(ParseContext::ZERO_NOTEQUAL, -1, -1);
1868 }
else if (in[j] ==
'v') {
1871 if (last_was_v)
return {};
1872 to_parse.emplace_back(ParseContext::VERIFY, -1, -1);
1873 }
else if (in[j] ==
'u') {
1875 to_parse.emplace_back(ParseContext::WRAP_U, -1, -1);
1876 }
else if (in[j] ==
't') {
1878 to_parse.emplace_back(ParseContext::WRAP_T, -1, -1);
1879 }
else if (in[j] ==
'l') {
1887 last_was_v = (in[j] ==
'v');
1889 to_parse.emplace_back(ParseContext::EXPR, -1, -1);
1890 if (colon_index) in = in.
subspan(*colon_index + 1);
1893 case ParseContext::EXPR: {
1894 if (
Const(
"0", in)) {
1896 }
else if (
Const(
"1", in)) {
1898 }
else if (
Const(
"pk(", in)) {
1899 auto res = ParseKeyEnd<Key, Ctx>(in, ctx);
1900 if (!res)
return {};
1901 auto& [key, key_size] = *res;
1903 in = in.subspan(key_size + 1);
1904 script_size +=
IsTapscript(ctx.MsContext()) ? 33 : 34;
1905 }
else if (
Const(
"pkh(", in)) {
1906 auto res = ParseKeyEnd<Key>(in, ctx);
1907 if (!res)
return {};
1908 auto& [key, key_size] = *res;
1910 in = in.subspan(key_size + 1);
1912 }
else if (
Const(
"pk_k(", in)) {
1913 auto res = ParseKeyEnd<Key>(in, ctx);
1914 if (!res)
return {};
1915 auto& [key, key_size] = *res;
1917 in = in.subspan(key_size + 1);
1918 script_size +=
IsTapscript(ctx.MsContext()) ? 32 : 33;
1919 }
else if (
Const(
"pk_h(", in)) {
1920 auto res = ParseKeyEnd<Key>(in, ctx);
1921 if (!res)
return {};
1922 auto& [key, key_size] = *res;
1924 in = in.subspan(key_size + 1);
1926 }
else if (
Const(
"sha256(", in)) {
1928 if (!res)
return {};
1929 auto& [hash, hash_size] = *res;
1931 in = in.
subspan(hash_size + 1);
1933 }
else if (
Const(
"ripemd160(", in)) {
1935 if (!res)
return {};
1936 auto& [hash, hash_size] = *res;
1938 in = in.
subspan(hash_size + 1);
1940 }
else if (
Const(
"hash256(", in)) {
1942 if (!res)
return {};
1943 auto& [hash, hash_size] = *res;
1945 in = in.
subspan(hash_size + 1);
1947 }
else if (
Const(
"hash160(", in)) {
1949 if (!res)
return {};
1950 auto& [hash, hash_size] = *res;
1952 in = in.
subspan(hash_size + 1);
1954 }
else if (
Const(
"after(", in)) {
1956 if (arg_size < 1)
return {};
1957 const auto num{ToIntegral<int64_t>(std::string_view(in.
begin(), arg_size))};
1958 if (!num.has_value() || *num < 1 || *num >= 0x80000000L)
return {};
1960 in = in.
subspan(arg_size + 1);
1961 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
1962 }
else if (
Const(
"older(", in)) {
1964 if (arg_size < 1)
return {};
1965 const auto num{ToIntegral<int64_t>(std::string_view(in.
begin(), arg_size))};
1966 if (!num.has_value() || *num < 1 || *num >= 0x80000000L)
return {};
1968 in = in.
subspan(arg_size + 1);
1969 script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
1970 }
else if (
Const(
"multi(", in)) {
1971 if (!parse_multi_exp(in,
false))
return {};
1972 }
else if (
Const(
"multi_a(", in)) {
1973 if (!parse_multi_exp(in,
true))
return {};
1974 }
else if (
Const(
"thresh(", in)) {
1976 if (next_comma < 1)
return {};
1977 const auto k{ToIntegral<int64_t>(std::string_view(in.
begin(), next_comma))};
1978 if (!
k.has_value() || *
k < 1)
return {};
1979 in = in.
subspan(next_comma + 1);
1982 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1983 script_size += 2 + (*
k > 16) + (*
k > 0x7f) + (*
k > 0x7fff) + (*
k > 0x7fffff);
1984 }
else if (
Const(
"andor(", in)) {
1986 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1);
1987 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1988 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
1989 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1990 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
1991 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
1994 if (
Const(
"and_n(", in)) {
1995 to_parse.emplace_back(ParseContext::AND_N, -1, -1);
1997 }
else if (
Const(
"and_b(", in)) {
2000 }
else if (
Const(
"and_v(", in)) {
2003 }
else if (
Const(
"or_b(", in)) {
2006 }
else if (
Const(
"or_c(", in)) {
2009 }
else if (
Const(
"or_d(", in)) {
2012 }
else if (
Const(
"or_i(", in)) {
2018 to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1);
2019 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2020 to_parse.emplace_back(ParseContext::COMMA, -1, -1);
2021 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2025 case ParseContext::ALT: {
2029 case ParseContext::SWAP: {
2037 case ParseContext::DUP_IF: {
2041 case ParseContext::NON_ZERO: {
2045 case ParseContext::ZERO_NOTEQUAL: {
2049 case ParseContext::VERIFY: {
2050 script_size += (constructed.back()->GetType() <<
"x"_mst);
2054 case ParseContext::WRAP_U: {
2058 case ParseContext::WRAP_T: {
2066 case ParseContext::AND_N: {
2067 auto mid = std::move(constructed.back());
2068 constructed.pop_back();
2093 auto right = std::move(constructed.back());
2094 constructed.pop_back();
2095 auto mid = std::move(constructed.back());
2096 constructed.pop_back();
2101 if (in.
size() < 1)
return {};
2105 to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
2107 }
else if (in[0] ==
')') {
2108 if (
k > n)
return {};
2111 std::vector<NodeRef<Key>>
subs;
2112 for (
int i = 0; i < n; ++i) {
2113 subs.push_back(std::move(constructed.back()));
2114 constructed.pop_back();
2116 std::reverse(
subs.begin(),
subs.end());
2123 case ParseContext::COMMA: {
2124 if (in.
size() < 1 || in[0] !=
',')
return {};
2128 case ParseContext::CLOSE_BRACKET: {
2129 if (in.
size() < 1 || in[0] !=
')')
return {};
2137 assert(constructed.size() == 1);
2139 if (in.
size() > 0)
return {};
2141 tl_node->DuplicateKeyCheck(ctx);
2227 template<
typename Key,
typename Ctx,
typename I>
2231 std::vector<std::tuple<DecodeContext, int64_t, int64_t>> to_parse;
2232 std::vector<NodeRef<Key>> constructed;
2236 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2238 while (!to_parse.empty()) {
2240 if (!constructed.empty() && !constructed.back()->IsValid())
return {};
2243 auto [cur_context, n,
k] = to_parse.back();
2244 to_parse.pop_back();
2246 switch(cur_context) {
2247 case DecodeContext::SINGLE_BKV_EXPR: {
2248 if (in >= last)
return {};
2251 if (in[0].first ==
OP_1) {
2256 if (in[0].first ==
OP_0) {
2262 if (in[0].second.size() == 33 || in[0].second.size() == 32) {
2263 auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());
2264 if (!key)
return {};
2270 auto key = ctx.FromPKHBytes(in[2].second.begin(), in[2].second.end());
2271 if (!key)
return {};
2277 std::optional<int64_t> num;
2280 if (*num < 1 || *num > 0x7FFFFFFFL)
return {};
2286 if (num < 1 || num > 0x7FFFFFFFL)
return {};
2292 if (in[2].first ==
OP_SHA256 && in[1].second.size() == 32) {
2296 }
else if (in[2].first ==
OP_RIPEMD160 && in[1].second.size() == 20) {
2300 }
else if (in[2].first ==
OP_HASH256 && in[1].second.size() == 32) {
2304 }
else if (in[2].first ==
OP_HASH160 && in[1].second.size() == 20) {
2313 std::vector<Key>
keys;
2315 if (!n || last - in < 3 + *n)
return {};
2316 if (*n < 1 || *n > 20)
return {};
2317 for (
int i = 0; i < *n; ++i) {
2318 if (in[2 + i].second.size() != 33)
return {};
2319 auto key = ctx.FromPKBytes(in[2 + i].second.begin(), in[2 + i].second.end());
2320 if (!key)
return {};
2321 keys.push_back(std::move(*key));
2324 if (!
k || *k < 1 || *k > *n)
return {};
2326 std::reverse(
keys.begin(),
keys.end());
2331 if (last - in >= 4 && in[0].first ==
OP_NUMEQUAL) {
2337 if (last - in < 2 + *
k * 2)
return {};
2338 std::vector<Key>
keys;
2341 for (
int pos = 2;; pos += 2) {
2342 if (last - in < pos + 2)
return {};
2345 if (in[pos + 1].second.size() != 32)
return {};
2346 auto key = ctx.FromPKBytes(in[pos + 1].second.begin(), in[pos + 1].second.end());
2347 if (!key)
return {};
2348 keys.push_back(std::move(*key));
2354 if (
keys.size() < (size_t)*
k)
return {};
2355 in += 2 +
keys.size() * 2;
2356 std::reverse(
keys.begin(),
keys.end());
2367 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2373 to_parse.emplace_back(DecodeContext::VERIFY, -1, -1);
2374 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2380 to_parse.emplace_back(DecodeContext::ZERO_NOTEQUAL, -1, -1);
2381 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2386 if (*num < 1)
return {};
2388 to_parse.emplace_back(DecodeContext::THRESH_W, 0, *num);
2394 to_parse.emplace_back(DecodeContext::ENDIF, -1, -1);
2395 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2407 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2408 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2415 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2416 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2422 case DecodeContext::BKV_EXPR: {
2423 to_parse.emplace_back(DecodeContext::MAYBE_AND_V, -1, -1);
2424 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2427 case DecodeContext::W_EXPR: {
2429 if (in >= last)
return {};
2432 to_parse.emplace_back(DecodeContext::ALT, -1, -1);
2434 to_parse.emplace_back(DecodeContext::SWAP, -1, -1);
2436 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2439 case DecodeContext::MAYBE_AND_V: {
2445 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2449 case DecodeContext::SWAP: {
2450 if (in >= last || in[0].first !=
OP_SWAP || constructed.empty())
return {};
2455 case DecodeContext::ALT: {
2456 if (in >= last || in[0].first !=
OP_TOALTSTACK || constructed.empty())
return {};
2462 if (constructed.empty())
return {};
2466 case DecodeContext::DUP_IF: {
2467 if (constructed.empty())
return {};
2471 case DecodeContext::VERIFY: {
2472 if (constructed.empty())
return {};
2476 case DecodeContext::NON_ZERO: {
2477 if (constructed.empty())
return {};
2481 case DecodeContext::ZERO_NOTEQUAL: {
2482 if (constructed.empty())
return {};
2487 if (constructed.size() < 2)
return {};
2492 if (constructed.size() < 2)
return {};
2497 if (constructed.size() < 2)
return {};
2502 if (constructed.size() < 2)
return {};
2507 if (constructed.size() < 2)
return {};
2512 if (constructed.size() < 3)
return {};
2514 constructed.pop_back();
2516 constructed.pop_back();
2521 case DecodeContext::THRESH_W: {
2522 if (in >= last)
return {};
2523 if (in[0].first ==
OP_ADD) {
2525 to_parse.emplace_back(DecodeContext::THRESH_W, n+1,
k);
2526 to_parse.emplace_back(DecodeContext::W_EXPR, -1, -1);
2528 to_parse.emplace_back(DecodeContext::THRESH_E, n+1,
k);
2530 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2534 case DecodeContext::THRESH_E: {
2535 if (k < 1 || k > n || constructed.size() <
static_cast<size_t>(n))
return {};
2536 std::vector<NodeRef<Key>>
subs;
2537 for (
int i = 0; i < n; ++i) {
2539 constructed.pop_back();
2540 subs.push_back(std::move(sub));
2545 case DecodeContext::ENDIF: {
2546 if (in >= last)
return {};
2551 to_parse.emplace_back(DecodeContext::ENDIF_ELSE, -1, -1);
2552 to_parse.emplace_back(DecodeContext::BKV_EXPR, -1, -1);
2555 else if (in[0].first ==
OP_IF) {
2556 if (last - in >= 2 && in[1].first ==
OP_DUP) {
2558 to_parse.emplace_back(DecodeContext::DUP_IF, -1, -1);
2561 to_parse.emplace_back(DecodeContext::NON_ZERO, -1, -1);
2567 }
else if (in[0].first ==
OP_NOTIF) {
2569 to_parse.emplace_back(DecodeContext::ENDIF_NOTIF, -1, -1);
2576 case DecodeContext::ENDIF_NOTIF: {
2577 if (in >= last)
return {};
2585 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2588 case DecodeContext::ENDIF_ELSE: {
2589 if (in >= last)
return {};
2590 if (in[0].first ==
OP_IF) {
2593 }
else if (in[0].first ==
OP_NOTIF) {
2597 to_parse.emplace_back(DecodeContext::SINGLE_BKV_EXPR, -1, -1);
2605 if (constructed.size() != 1)
return {};
2607 tl_node->DuplicateKeyCheck(ctx);
2610 if (!tl_node->IsValidTopLevel())
return {};
2616 template<
typename Ctx>
2618 return internal::Parse<typename Ctx::Key>(str, ctx);
2621 template<
typename Ctx>
2623 using namespace internal;
2627 if (!decomposed)
return {};
2628 auto it = decomposed->begin();
2629 auto ret = DecodeScript<typename Ctx::Key>(it, decomposed->end(), ctx);
2630 if (!
ret)
return {};
2631 if (it != decomposed->end())
return {};
2637 #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, Fragment nt, std::vector< unsigned char > arg, uint32_t val=0)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
A node in a miniscript expression.
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
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:
static constexpr SatInfo BinaryOp() noexcept
A script consisting of just a binary operator (OP_BOOLAND, OP_BOOLOR, OP_ADD).
bool IsNotSatisfiable() const
Whether no satisfaction exists for this node.
friend MaxInt< I > operator+(const MaxInt< I > &a, const MaxInt< I > &b)
[X] OP_NOTIF [Z] OP_ELSE [Y] OP_ENDIF
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...
static const auto ZERO32
A stack consisting of a single malleable 32-byte 0x0000...0000 element (for dissatisfying hash challe...
Node(const Ctx &ctx, Fragment nt, std::vector< unsigned char > arg, uint32_t val=0)
std::optional< std::pair< Key, int > > ParseKeyEnd(Span< const char > in, const Ctx &ctx)
Parse a key string ending at the end of the fragment's text representation.
const MiniscriptContext m_script_ctx
The Script context for this node. Either P2WSH or Tapscript.
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.
ALT wraps the top constructed node with a:
constexpr uint32_t TXIN_BYTES_NO_WITNESS
prevout + nSequence + scriptSig
const std::vector< unsigned char > data
The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD10).
VERIFY wraps the top constructed node with v:
OP_SIZE 32 OP_EQUALVERIFY OP_RIPEMD160 [hash] OP_EQUAL.
const Node * FindInsaneSub() const
Find an insane subnode which has no insane children. Nullptr if there is none.
std::optional< Result > TreeEvalMaybe(UpFn upfn) const
Like TreeEvalMaybe, but without downfn or State type.
[k] [key_n]* [n] OP_CHECKMULTISIG (only available within P2WSH context)
std::optional< Result > TreeEvalMaybe(State root_state, DownFn downfn, UpFn upfn) const
[n] OP_CHECKLOCKTIMEVERIFY
constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept
Script set with a single script in it, with specified netdiff and exec.
bool CheckDuplicateKey() const
Check whether there is no duplicate key across this fragment and all its sub-fragments.
OP_TOALTSTACK [X] OP_FROMALTSTACK.
const uint32_t k
The k parameter (time for OLDER/AFTER, threshold for THRESH(_M))
#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)
bool IsValid() const
Check whether this node is valid at all.
constexpr std::size_t size() const noexcept
If, inside an ENDIF context, we find an OP_NOTIF before finding an OP_ELSE, we could either be in an ...
std::optional< std::pair< std::vector< unsigned char >, int > > ParseHexStrEnd(Span< const char > in, const size_t expected_size, const Ctx &ctx)
Parse a hex string ending at the end of the fragment's text representation.
static consteval Type Make(uint32_t flags) noexcept
Construction function used by the ""_mst operator.
const internal::WitnessSize ws
Cached witness size bounds.
Type CalcType() const
Compute the type for this miniscript.
static const auto ONE
A stack consisting of a single 0x01 element (interpreted as 1 by the script interpreted in numeric co...
static constexpr SatInfo Nop() noexcept
A script consisting of just a repurposed nop (OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY).
Node(const Ctx &ctx, Fragment nt, std::vector< NodeRef< Key >> sub, std::vector< Key > key, uint32_t val=0)
WRAP_U will construct an or_i(X,0) node from the top constructed node.
size_t CalcScriptLen() const
Compute the length of the script for this miniscript (including children).
constexpr SatInfo() noexcept
Empty script set.
Ops(uint32_t in_count, MaxInt< uint32_t > in_sat, MaxInt< uint32_t > in_dsat)
ZERO_NOTEQUAL wraps the top constructed node with n:
std::optional< uint32_t > GetWitnessSize() const
Return the maximum size in bytes of a witness to satisfy this script non-malleably.
[X] OP_NOTIF [Y] OP_ENDIF
std::optional< bool > has_duplicate_keys
Whether a public key appears more than once in this node.
WRAP_T will construct an and_v(X,1) node from the top constructed node.
MaxInt< uint32_t > dsat
Maximum witness size to dissatisfy;.
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.
bool IsSane() const
Check whether this node is safe as a script on its own.
Node(const Ctx &ctx, Fragment nt, uint32_t val=0)
constexpr Type If(bool x) const
The empty type if x is false, itself otherwise.
NodeRef< Key > DecodeScript(I &in, I last, const Ctx &ctx)
Parse a miniscript from a bitcoin script.
AND_N will construct an andor(X,Y,0) node from the last two constructed nodes.
[X] OP_IFDUP OP_NOTIF [Y] OP_ENDIF
uint32_t GetStaticOps() const
Return the number of ops in the script (not counting the dynamic ones that depend on execution)...
static constexpr SatInfo OP_SIZE() noexcept
const Type typ
Cached expression type (computed by CalcType and fed through SanitizeType).
An expression which may be begin with wrappers followed by a colon.
const size_t scriptlen
Cached script length (computed by CalcScriptLen).
State
The various states a (txhash,peer) pair can be in.
static const int MAX_PUBKEYS_PER_MULTISIG
static constexpr SatInfo OP_0NOTEQUAL() noexcept
CLOSE_BRACKET expects the next element to be ')' and fails if not.
const Fragment fragment
What node type this node is.
std::pair< opcodetype, std::vector< unsigned char > > Opcode
std::shared_ptr< const Node< Key > > NodeRef
[X1] ([Xn] OP_ADD)* [k] OP_EQUAL
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, uint32_t val=0)
internal::InputResult ProduceInput(const Ctx &ctx) const
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
const int32_t netdiff
How much higher the stack size at start of execution can be compared to at the end.
const int32_t exec
Mow much higher the stack size can be during execution compared to at the end.
int FindNextChar(Span< const char > sp, const char m)
uint32_t count
Non-push opcodes.
constexpr bool operator==(Type x) const
Equality operator.
constexpr StackSize(SatInfo in_both) noexcept
A single expression of type B, K, or V.
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.
internal::Ops CalcOps() const
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.
A miniscript expression which does not begin with wrappers.
bool IsNonMalleable() const
Check whether this script can always be satisfied in a non-malleable way.
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.
[n] OP_CHECKSEQUENCEVERIFY
Node(const Ctx &ctx, Fragment nt, std::vector< NodeRef< Key >> sub, std::vector< unsigned char > arg, uint32_t val=0)
bool IsSaneSubexpression() const
Whether the apparent policy of this node matches its script semantics. Doesn't guarantee it is a safe...
constexpr friend SatInfo operator|(const SatInfo &a, const SatInfo &b) noexcept
Script set union.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector< Key > key, uint32_t val=0)
friend int Compare(const Node< Key > &node1, const Node< Key > &node2)
Compare two miniscript subtrees, using a non-recursive algorithm.
A data structure to help the calculation of stack size limits.
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.
bool NeedsSignature() const
Check whether this script always needs a signature.
MiniscriptContext GetMsCtx() const
Return the script context for this node.
constexpr uint32_t P2WSH_TXOUT_BYTES
nValue + script len + OP_0 + pushdata 32.
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.
Class whose objects represent the maximum of a list of integers.
const bool valid
Whether a canonical satisfaction/dissatisfaction is possible at all.
COMMA expects the next element to be ',' and fails if not.
bool Const(const std::string &str, Span< const char > &sp)
Parse a constant.
#define CHECK(cond)
Unconditional failure on condition failure.
internal::WitnessSize CalcWitnessSize() const
static const auto ZERO
A stack consisting of a single zero-length element (interpreted as 0 by the script interpreter in num...
size_t ScriptSize() const
Return the size of the script for this expression (faster than ToScript().size()).
static constexpr SatInfo OP_CHECKSIG() noexcept
THRESH_E constructs a thresh node from the appropriate number of constructed children.
static constexpr size_t TAPROOT_CONTROL_MAX_SIZE
constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept
Node(const Ctx &ctx, Fragment nt, std::vector< Key > key, uint32_t val=0)
NodeRef< Key > Parse(Span< const char > in, const Ctx &ctx)
Parse a miniscript from its textual descriptor form.
std::optional< std::string > ToString(const CTx &ctx) const
constexpr friend SatInfo operator+(const SatInfo &a, const SatInfo &b) noexcept
Script set concatenation.
MaxInt< uint32_t > sat
Number of keys in possibly executed OP_CHECKMULTISIG(VERIFY)s to satisfy.
constexpr C * begin() const noexcept
OP_SIZE OP_0NOTEQUAL OP_IF [X] OP_ENDIF.
const std::vector< Key > keys
The keys used by this expression (only for PK_K/PK_H/MULTI)
bool operator==(const Node< Key > &arg) const
Equality testing.
static constexpr SatInfo Empty() noexcept
The empty script.
static constexpr int32_t MAX_STANDARD_TX_WEIGHT
The maximum weight for transactions we're willing to relay/mine.
bool IsSatisfiable(F fn) const
Determine whether a Miniscript node is satisfiable.
friend MaxInt< I > operator|(const MaxInt< I > &a, const MaxInt< I > &b)
constexpr Type operator|(Type x) const
Compute the type with the union of properties.
Result TreeEval(State root_state, DownFn &&downfn, UpFn upfn) const
Like TreeEvalMaybe, but always produces a result.
std::optional< uint32_t > GetOps() const
Return the maximum number of ops needed to satisfy this script non-malleably.
bool CheckStackSize() const
Check the maximum stack size for this script against the policy limit.
Node(const Ctx &ctx, Fragment nt, std::vector< NodeRef< Key >> sub, uint32_t val=0)
constexpr uint32_t MAX_TAPSCRIPT_SAT_SIZE
Maximum possible stack size to spend a Taproot output (excluding the script itself).
Serialized script, used inside transaction inputs and outputs.
static const int MAX_OPS_PER_SCRIPT
Fragment
The different node types in miniscript.
bool IsBKW() const
Whether this node is of type B, K or W.
static constexpr SatInfo Hash() noexcept
A script consisting of a single hash opcode.
static constexpr SatInfo OP_DUP() noexcept
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)...
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_VERIFY() noexcept
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::vector< NodeRef< Key > > subs
Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH)
static constexpr SatInfo OP_IFDUP(bool nonzero) noexcept
NodeRef< Key > MakeNodeRef(Args &&... args)
Construct a miniscript node as a shared_ptr.
std::optional< uint32_t > GetStackSize() const
Return the maximum number of stack elements needed to satisfy this script non-malleably.
DUP_IF wraps the top constructed node with d:
const internal::StackSize ss
Cached stack size bounds.
bool IsValidTopLevel() const
Check whether this node is valid as a script on its own.
std::optional< uint32_t > GetExecStackSize() const
Return the maximum size of the stack during execution of this script.
OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 [hash] OP_EQUAL.
void DuplicateKeyCheck(const Ctx &ctx) const
Update duplicate key information in this Node.
An expression of type W (a: or s: wrappers).
constexpr bool operator<(Type x) const
Comparison operator to enable use in sets/maps (total ordering incompatible with <<).
bool ValidSatisfactions() const
Whether successful non-malleable satisfactions are guaranteed to be valid.
A Span is an object that can refer to a contiguous sequence of objects.
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
constexpr Type(uint32_t flags) noexcept
Internal constructor.
static constexpr SatInfo Push() noexcept
A script consisting of a single push opcode.
Type GetType() const
Return the expression type.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
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
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector< NodeRef< Key >> sub, uint32_t val=0)
Result TreeEval(UpFn upfn) const
Like TreeEval, but without downfn or State type.
constexpr uint32_t MaxScriptSize(MiniscriptContext ms_ctx)
The maximum size of a script depending on the context.
static const int MAX_STACK_SIZE
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector< NodeRef< Key >> sub, std::vector< unsigned char > arg, uint32_t val=0)
CONSTEXPR_IF_NOT_DEBUG Span< C > last(std::size_t count) const noexcept
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector< NodeRef< Key >> sub, std::vector< Key > key, uint32_t val=0)
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...
void BuildBack(const MiniscriptContext script_ctx, Fragment nt, std::vector< NodeRef< Key >> &constructed, const bool reverse=false)
BuildBack pops the last two elements off constructed and wraps them in the specified Fragment...
constexpr uint32_t TX_BODY_LEEWAY_WEIGHT
Data other than the witness in a transaction. Overhead + vin count + one vin + vout count + one vout ...
static constexpr SatInfo OP_EQUALVERIFY() noexcept
This type encapsulates the miniscript type system properties.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static const auto INVALID
A stack representing the lack of any (dis)satisfactions.
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...
static constexpr SatInfo If() noexcept
A script consisting of just OP_IF or OP_NOTIF.
const internal::Ops ops
Cached ops counts.
CScript ToScript(const Ctx &ctx) const
std::optional< int64_t > ParseScriptNumber(const Opcode &in)
Determine whether the passed pair (created by DecomposeScript) is pushing a number.
internal::StackSize CalcStackSize() const
constexpr uint32_t TX_OVERHEAD
version + nLockTime
bool CheckTimeLocksMix() const
Check whether there is no satisfaction path that contains both timelocks and heightlocks.
static constexpr SatInfo OP_EQUAL() noexcept