refactor(miniscript): Make fields non-const & private

Makes a lot of fields in miniscript.h non-const in order to allow move-operations 2 commits later.

Also fixes adjacent comment typos.

Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
This commit is contained in:
committed 2026-01-20 22:35:03 +01:00
1 parent 22e4115312
commit c6f798b222
4 files changed
+110 -86

No files matched your search

+2 -2
View File
@@ -1607,8 +1607,8 @@ public:
{ {
// Traverse miniscript tree for unsafe use of older() // Traverse miniscript tree for unsafe use of older()
miniscript::ForEachNode(*m_node, [&](const miniscript::Node<uint32_t>& node) { miniscript::ForEachNode(*m_node, [&](const miniscript::Node<uint32_t>& node) {
if (node.fragment == miniscript::Fragment::OLDER) { if (node.Fragment() == miniscript::Fragment::OLDER) {
const uint32_t raw = node.k; const uint32_t raw = node.K();
const uint32_t value_part = raw & ~CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG; const uint32_t value_part = raw & ~CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
if (value_part > CTxIn::SEQUENCE_LOCKTIME_MASK) { if (value_part > CTxIn::SEQUENCE_LOCKTIME_MASK) {
const bool is_time_based = (raw & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) != 0; const bool is_time_based = (raw & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) != 0;
+89 -65
View File
@@ -190,7 +190,7 @@ inline consteval Type operator""_mst(const char* c, size_t l)
using Opcode = std::pair<opcodetype, std::vector<unsigned char>>; using Opcode = std::pair<opcodetype, std::vector<unsigned char>>;
template<typename Key> struct Node; template<typename Key> class Node;
template<typename Key> using NodeRef = std::unique_ptr<const Node<Key>>; template<typename Key> using NodeRef = std::unique_ptr<const Node<Key>>;
//! Construct a miniscript node as a unique_ptr. //! Construct a miniscript node as a unique_ptr.
@@ -206,7 +206,7 @@ void ForEachNode(const Node<Key>& root, Fn&& fn)
const Node<Key>& node = stack.back(); const Node<Key>& node = stack.back();
std::invoke(fn, node); std::invoke(fn, node);
stack.pop_back(); stack.pop_back();
for (const auto& sub : node.subs) { for (const auto& sub : node.Subs()) {
stack.emplace_back(*sub); stack.emplace_back(*sub);
} }
} }
@@ -364,14 +364,19 @@ struct InputResult {
}; };
//! Class whose objects represent the maximum of a list of integers. //! Class whose objects represent the maximum of a list of integers.
template<typename I> template <typename I>
struct MaxInt { class MaxInt
const bool valid; {
const I value; bool valid;
I value;
public:
MaxInt() : valid(false), value(0) {} MaxInt() : valid(false), value(0) {}
MaxInt(I val) : valid(true), value(val) {} MaxInt(I val) : valid(true), value(val) {}
bool Valid() const { return valid; }
I Value() const { return value; }
friend MaxInt<I> operator+(const MaxInt<I>& a, const MaxInt<I>& b) { friend MaxInt<I> operator+(const MaxInt<I>& a, const MaxInt<I>& b) {
if (!a.valid || !b.valid) return {}; if (!a.valid || !b.valid) return {};
return a.value + b.value; return a.value + b.value;
@@ -436,14 +441,16 @@ struct Ops {
* - It is not a commutative semiring, because a+b can differ from b+a. For example, "OP_1 OP_DROP" * - It is not a commutative semiring, because a+b can differ from b+a. For example, "OP_1 OP_DROP"
* has exec=1, while "OP_DROP OP_1" has exec=0. * has exec=1, while "OP_DROP OP_1" has exec=0.
*/ */
struct SatInfo { class SatInfo
{
//! Whether a canonical satisfaction/dissatisfaction is possible at all. //! Whether a canonical satisfaction/dissatisfaction is possible at all.
const bool valid; bool valid;
//! How much higher the stack size at start of execution can be compared to at the end. //! How much higher the stack size at start of execution can be compared to at the end.
const int32_t netdiff; int32_t netdiff;
//! Mow much higher the stack size can be during execution compared to at the end. //! How much higher the stack size can be during execution compared to at the end.
const int32_t exec; int32_t exec;
public:
/** Empty script set. */ /** Empty script set. */
constexpr SatInfo() noexcept : valid(false), netdiff(0), exec(0) {} constexpr SatInfo() noexcept : valid(false), netdiff(0), exec(0) {}
@@ -451,6 +458,10 @@ struct SatInfo {
constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept : constexpr SatInfo(int32_t in_netdiff, int32_t in_exec) noexcept :
valid{true}, netdiff{in_netdiff}, exec{in_exec} {} valid{true}, netdiff{in_netdiff}, exec{in_exec} {}
bool Valid() const { return valid; }
int32_t NetDiff() const { return netdiff; }
int32_t Exec() const { return exec; }
/** Script set union. */ /** Script set union. */
constexpr friend SatInfo operator|(const SatInfo& a, const SatInfo& b) noexcept constexpr friend SatInfo operator|(const SatInfo& a, const SatInfo& b) noexcept
{ {
@@ -496,11 +507,16 @@ struct SatInfo {
static constexpr SatInfo OP_VERIFY() noexcept { return {1, 1}; } static constexpr SatInfo OP_VERIFY() noexcept { return {1, 1}; }
}; };
struct StackSize { class StackSize
const SatInfo sat, dsat; {
SatInfo sat, dsat;
public:
constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept : sat(in_sat), dsat(in_dsat) {}; constexpr StackSize(SatInfo in_sat, SatInfo in_dsat) noexcept : sat(in_sat), dsat(in_dsat) {};
constexpr StackSize(SatInfo in_both) noexcept : sat(in_both), dsat(in_both) {}; constexpr StackSize(SatInfo in_both) noexcept : sat(in_both), dsat(in_both) {};
const SatInfo& Sat() const { return sat; }
const SatInfo& Dsat() const { return dsat; }
}; };
struct WitnessSize { struct WitnessSize {
@@ -517,21 +533,23 @@ struct NoDupCheck {};
} // namespace internal } // namespace internal
//! A node in a miniscript expression. //! A node in a miniscript expression.
template<typename Key> template <typename Key>
struct Node { class Node
{
//! What node type this node is. //! What node type this node is.
const Fragment fragment; enum Fragment fragment;
//! The k parameter (time for OLDER/AFTER, threshold for THRESH(_M)) //! The k parameter (time for OLDER/AFTER, threshold for THRESH(_M))
const uint32_t k = 0; uint32_t k = 0;
//! The keys used by this expression (only for PK_K/PK_H/MULTI) //! The keys used by this expression (only for PK_K/PK_H/MULTI)
const std::vector<Key> keys; std::vector<Key> keys;
//! The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD10). //! The data bytes in this expression (only for HASH160/HASH256/SHA256/RIPEMD160).
const std::vector<unsigned char> data; std::vector<unsigned char> data;
//! Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH) //! Subexpressions (for WRAP_*/AND_*/OR_*/ANDOR/THRESH)
mutable std::vector<NodeRef<Key>> subs; mutable std::vector<NodeRef<Key>> subs;
//! The Script context for this node. Either P2WSH or Tapscript. //! The Script context for this node. Either P2WSH or Tapscript.
const MiniscriptContext m_script_ctx; MiniscriptContext m_script_ctx;
public:
~Node() ~Node()
{ {
// Destroy the subexpressions iteratively after moving out their // Destroy the subexpressions iteratively after moving out their
@@ -561,17 +579,23 @@ struct Node {
return TreeEval<NodeRef<Key>>(upfn); return TreeEval<NodeRef<Key>>(upfn);
} }
enum Fragment Fragment() const { return fragment; }
uint32_t K() const { return k; }
const std::vector<Key>& Keys() const { return keys; }
const std::vector<unsigned char>& Data() const { return data; }
const std::vector<NodeRef<Key>>& Subs() const { return subs; }
private: private:
//! Cached ops counts. //! Cached ops counts.
const internal::Ops ops; internal::Ops ops;
//! Cached stack size bounds. //! Cached stack size bounds.
const internal::StackSize ss; internal::StackSize ss;
//! Cached witness size bounds. //! Cached witness size bounds.
const internal::WitnessSize ws; internal::WitnessSize ws;
//! Cached expression type (computed by CalcType and fed through SanitizeType). //! Cached expression type (computed by CalcType and fed through SanitizeType).
const Type typ; Type typ;
//! Cached script length (computed by CalcScriptLen). //! Cached script length (computed by CalcScriptLen).
const size_t scriptlen; size_t scriptlen;
//! Whether a public key appears more than once in this node. This value is initialized //! Whether a public key appears more than once in this node. This value is initialized
//! by all constructors except the NoDupCheck ones. The NoDupCheck ones skip the //! by all constructors except the NoDupCheck ones. The NoDupCheck ones skip the
//! computation, requiring it to be done manually by invoking DuplicateKeyCheck(). //! computation, requiring it to be done manually by invoking DuplicateKeyCheck().
@@ -582,7 +606,7 @@ private:
// Constructor which takes all of the data that a Node could possibly contain. // Constructor which takes all of the data that a Node could possibly contain.
// This is kept private as no valid fragment has all of these arguments. // This is kept private as no valid fragment has all of these arguments.
// Only used by Clone() // Only used by Clone()
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, std::vector<unsigned char> arg, uint32_t val) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, std::vector<unsigned char> arg, uint32_t val)
: 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()) {} : 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()) {}
//! Compute the length of the script for this miniscript (including children). //! Compute the length of the script for this miniscript (including children).
@@ -1066,45 +1090,45 @@ private:
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
const auto& z{subs[2]->ss}; const auto& z{subs[2]->ss};
return { return {
(x.sat + SatInfo::If() + y.sat) | (x.dsat + SatInfo::If() + z.sat), (x.Sat() + SatInfo::If() + y.Sat()) | (x.Dsat() + SatInfo::If() + z.Sat()),
x.dsat + SatInfo::If() + z.dsat x.Dsat() + SatInfo::If() + z.Dsat()
}; };
} }
case Fragment::AND_V: { case Fragment::AND_V: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return {x.sat + y.sat, {}}; return {x.Sat() + y.Sat(), {}};
} }
case Fragment::AND_B: { case Fragment::AND_B: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return {x.sat + y.sat + SatInfo::BinaryOp(), x.dsat + y.dsat + SatInfo::BinaryOp()}; return {x.Sat() + y.Sat() + SatInfo::BinaryOp(), x.Dsat() + y.Dsat() + SatInfo::BinaryOp()};
} }
case Fragment::OR_B: { case Fragment::OR_B: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return { return {
((x.sat + y.dsat) | (x.dsat + y.sat)) + SatInfo::BinaryOp(), ((x.Sat() + y.Dsat()) | (x.Dsat() + y.Sat())) + SatInfo::BinaryOp(),
x.dsat + y.dsat + SatInfo::BinaryOp() x.Dsat() + y.Dsat() + SatInfo::BinaryOp()
}; };
} }
case Fragment::OR_C: { case Fragment::OR_C: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return {(x.sat + SatInfo::If()) | (x.dsat + SatInfo::If() + y.sat), {}}; return {(x.Sat() + SatInfo::If()) | (x.Dsat() + SatInfo::If() + y.Sat()), {}};
} }
case Fragment::OR_D: { case Fragment::OR_D: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return { return {
(x.sat + SatInfo::OP_IFDUP(true) + SatInfo::If()) | (x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.sat), (x.Sat() + SatInfo::OP_IFDUP(true) + SatInfo::If()) | (x.Dsat() + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.Sat()),
x.dsat + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.dsat x.Dsat() + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.Dsat()
}; };
} }
case Fragment::OR_I: { case Fragment::OR_I: {
const auto& x{subs[0]->ss}; const auto& x{subs[0]->ss};
const auto& y{subs[1]->ss}; const auto& y{subs[1]->ss};
return {SatInfo::If() + (x.sat | y.sat), SatInfo::If() + (x.dsat | y.dsat)}; return {SatInfo::If() + (x.Sat() | y.Sat()), SatInfo::If() + (x.Dsat() | y.Dsat())};
} }
// multi(k, key1, key2, ..., key_n) starts off with k+1 stack elements (a 0, plus k // multi(k, key1, key2, ..., key_n) starts off with k+1 stack elements (a 0, plus k
// signatures), then reaches n+k+3 stack elements after pushing the n keys, plus k and // signatures), then reaches n+k+3 stack elements after pushing the n keys, plus k and
@@ -1119,16 +1143,16 @@ private:
case Fragment::WRAP_N: case Fragment::WRAP_N:
case Fragment::WRAP_S: return subs[0]->ss; case Fragment::WRAP_S: return subs[0]->ss;
case Fragment::WRAP_C: return { case Fragment::WRAP_C: return {
subs[0]->ss.sat + SatInfo::OP_CHECKSIG(), subs[0]->ss.Sat() + SatInfo::OP_CHECKSIG(),
subs[0]->ss.dsat + SatInfo::OP_CHECKSIG() subs[0]->ss.Dsat() + SatInfo::OP_CHECKSIG()
}; };
case Fragment::WRAP_D: return { case Fragment::WRAP_D: return {
SatInfo::OP_DUP() + SatInfo::If() + subs[0]->ss.sat, SatInfo::OP_DUP() + SatInfo::If() + subs[0]->ss.Sat(),
SatInfo::OP_DUP() + SatInfo::If() SatInfo::OP_DUP() + SatInfo::If()
}; };
case Fragment::WRAP_V: return {subs[0]->ss.sat + SatInfo::OP_VERIFY(), {}}; case Fragment::WRAP_V: return {subs[0]->ss.Sat() + SatInfo::OP_VERIFY(), {}};
case Fragment::WRAP_J: return { case Fragment::WRAP_J: return {
SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() + subs[0]->ss.sat, SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() + subs[0]->ss.Sat(),
SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If()
}; };
case Fragment::THRESH: { case Fragment::THRESH: {
@@ -1139,13 +1163,13 @@ private:
// element i we need to add OP_ADD (if i>0). // element i we need to add OP_ADD (if i>0).
auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty(); auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty();
// Construct a variable that will become the next sats, starting with index 0. // Construct a variable that will become the next sats, starting with index 0.
auto next_sats = Vector(sats[0] + subs[i]->ss.dsat + add); auto next_sats = Vector(sats[0] + subs[i]->ss.Dsat() + add);
// Then loop to construct next_sats[1..i]. // Then loop to construct next_sats[1..i].
for (size_t j = 1; j < sats.size(); ++j) { for (size_t j = 1; j < sats.size(); ++j) {
next_sats.push_back(((sats[j] + subs[i]->ss.dsat) | (sats[j - 1] + subs[i]->ss.sat)) + add); next_sats.push_back(((sats[j] + subs[i]->ss.Dsat()) | (sats[j - 1] + subs[i]->ss.Sat())) + add);
} }
// Finally construct next_sats[i+1]. // Finally construct next_sats[i+1].
next_sats.push_back(sats[sats.size() - 1] + subs[i]->ss.sat + add); next_sats.push_back(sats[sats.size() - 1] + subs[i]->ss.Sat() + add);
// Switch over. // Switch over.
sats = std::move(next_sats); sats = std::move(next_sats);
} }
@@ -1530,8 +1554,8 @@ public:
//! Return the maximum number of ops needed to satisfy this script non-malleably. //! Return the maximum number of ops needed to satisfy this script non-malleably.
std::optional<uint32_t> GetOps() const { std::optional<uint32_t> GetOps() const {
if (!ops.sat.valid) return {}; if (!ops.sat.Valid()) return {};
return ops.count + ops.sat.value; return ops.count + ops.sat.Value();
} }
//! Return the number of ops in the script (not counting the dynamic ones that depend on execution). //! Return the number of ops in the script (not counting the dynamic ones that depend on execution).
@@ -1551,14 +1575,14 @@ public:
/** Return the maximum number of stack elements needed to satisfy this script non-malleably. */ /** Return the maximum number of stack elements needed to satisfy this script non-malleably. */
std::optional<uint32_t> GetStackSize() const { std::optional<uint32_t> GetStackSize() const {
if (!ss.sat.valid) return {}; if (!ss.Sat().Valid()) return {};
return ss.sat.netdiff + static_cast<int32_t>(IsBKW()); return ss.Sat().NetDiff() + static_cast<int32_t>(IsBKW());
} }
//! Return the maximum size of the stack during execution of this script. //! Return the maximum size of the stack during execution of this script.
std::optional<uint32_t> GetExecStackSize() const { std::optional<uint32_t> GetExecStackSize() const {
if (!ss.sat.valid) return {}; if (!ss.Sat().Valid()) return {};
return ss.sat.exec + static_cast<int32_t>(IsBKW()); return ss.Sat().Exec() + static_cast<int32_t>(IsBKW());
} }
//! Check the maximum stack size for this script against the policy limit. //! Check the maximum stack size for this script against the policy limit.
@@ -1579,8 +1603,8 @@ public:
/** Return the maximum size in bytes of a witness to satisfy this script non-malleably. Note this does /** Return the maximum size in bytes of a witness to satisfy this script non-malleably. Note this does
* not include the witness script push. */ * not include the witness script push. */
std::optional<uint32_t> GetWitnessSize() const { std::optional<uint32_t> GetWitnessSize() const {
if (!ws.sat.valid) return {}; if (!ws.sat.Valid()) return {};
return ws.sat.value; return ws.sat.Value();
} }
//! Return the expression type. //! Return the expression type.
@@ -1687,31 +1711,31 @@ public:
bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; } bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; }
// Constructors with various argument combinations, which bypass the duplicate key check. // Constructors with various argument combinations, which bypass the duplicate key check.
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0)
: fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), data(std::move(arg)), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
: fragment(nt), k(val), data(std::move(arg)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), data(std::move(arg)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0)
: fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<Key> key, uint32_t val = 0)
: fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), keys(std::move(key)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0)
: fragment(nt), k(val), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), subs(std::move(sub)), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
Node(internal::NoDupCheck, MiniscriptContext script_ctx, Fragment nt, uint32_t val = 0) Node(internal::NoDupCheck, MiniscriptContext script_ctx, enum Fragment nt, uint32_t val = 0)
: fragment(nt), k(val), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {} : fragment(nt), k(val), m_script_ctx{script_ctx}, ops(CalcOps()), ss(CalcStackSize()), ws(CalcWitnessSize()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
// Constructors with various argument combinations, which do perform the duplicate key check. // Constructors with various argument combinations, which do perform the duplicate key check.
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<unsigned char> arg, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) { DuplicateKeyCheck(ctx); } : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(arg), val) { DuplicateKeyCheck(ctx); }
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(arg), val) { DuplicateKeyCheck(ctx);} : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(arg), val) { DuplicateKeyCheck(ctx);}
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, std::vector<Key> key, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) { DuplicateKeyCheck(ctx); } : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), std::move(key), val) { DuplicateKeyCheck(ctx); }
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, std::vector<Key> key, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) { DuplicateKeyCheck(ctx); } : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(key), val) { DuplicateKeyCheck(ctx); }
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) { DuplicateKeyCheck(ctx); } : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, std::move(sub), val) { DuplicateKeyCheck(ctx); }
template <typename Ctx> Node(const Ctx& ctx, Fragment nt, uint32_t val = 0) template <typename Ctx> Node(const Ctx& ctx, enum Fragment nt, uint32_t val = 0)
: Node(internal::NoDupCheck{}, ctx.MsContext(), nt, val) { DuplicateKeyCheck(ctx); } : Node(internal::NoDupCheck{}, ctx.MsContext(), nt, val) { DuplicateKeyCheck(ctx); }
// Delete copy constructor and assignment operator, use Clone() instead // Delete copy constructor and assignment operator, use Clone() instead
+10 -10
View File
@@ -991,7 +991,7 @@ NodeRef GenNode(MsCtx script_ctx, F ConsumeNode, Type root_type, bool strict_val
} }
if (!node->IsValid()) return {}; if (!node->IsValid()) return {};
// Update resource predictions. // Update resource predictions.
if (node->fragment == Fragment::WRAP_V && node->subs[0]->GetType() << "x"_mst) { if (node->Fragment() == Fragment::WRAP_V && node->Subs()[0]->GetType() << "x"_mst) {
ops += 1; ops += 1;
scriptsize += 1; scriptsize += 1;
} }
@@ -1167,28 +1167,28 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
return sig_ptr != nullptr && sig_ptr->second; return sig_ptr != nullptr && sig_ptr->second;
}; };
bool satisfiable = node->IsSatisfiable([&](const Node& node) -> bool { bool satisfiable = node->IsSatisfiable([&](const Node& node) -> bool {
switch (node.fragment) { switch (node.Fragment()) {
case Fragment::PK_K: case Fragment::PK_K:
case Fragment::PK_H: case Fragment::PK_H:
return is_key_satisfiable(node.keys[0]); return is_key_satisfiable(node.Keys()[0]);
case Fragment::MULTI: case Fragment::MULTI:
case Fragment::MULTI_A: { case Fragment::MULTI_A: {
size_t sats = std::count_if(node.keys.begin(), node.keys.end(), [&](const auto& key) { size_t sats = std::ranges::count_if(node.Keys(), [&](const auto& key) {
return size_t(is_key_satisfiable(key)); return size_t(is_key_satisfiable(key));
}); });
return sats >= node.k; return sats >= node.K();
} }
case Fragment::OLDER: case Fragment::OLDER:
case Fragment::AFTER: case Fragment::AFTER:
return node.k & 1; return node.K() & 1;
case Fragment::SHA256: case Fragment::SHA256:
return TEST_DATA.sha256_preimages.contains(node.data); return TEST_DATA.sha256_preimages.contains(node.Data());
case Fragment::HASH256: case Fragment::HASH256:
return TEST_DATA.hash256_preimages.contains(node.data); return TEST_DATA.hash256_preimages.contains(node.Data());
case Fragment::RIPEMD160: case Fragment::RIPEMD160:
return TEST_DATA.ripemd160_preimages.contains(node.data); return TEST_DATA.ripemd160_preimages.contains(node.Data());
case Fragment::HASH160: case Fragment::HASH160:
return TEST_DATA.hash160_preimages.contains(node.data); return TEST_DATA.hash160_preimages.contains(node.Data());
default: default:
assert(false); assert(false);
} }
+9 -9
View File
@@ -305,19 +305,19 @@ std::set<Challenge> FindChallenges(const Node* root)
const auto* ref{stack.back()}; const auto* ref{stack.back()};
stack.pop_back(); stack.pop_back();
for (const auto& key : ref->keys) { for (const auto& key : ref->Keys()) {
chal.emplace(ChallengeType::PK, ChallengeNumber(key)); chal.emplace(ChallengeType::PK, ChallengeNumber(key));
} }
switch (ref->fragment) { switch (ref->Fragment()) {
case Fragment::OLDER: chal.emplace(ChallengeType::OLDER, ref->k); break; case Fragment::OLDER: chal.emplace(ChallengeType::OLDER, ref->K()); break;
case Fragment::AFTER: chal.emplace(ChallengeType::AFTER, ref->k); break; case Fragment::AFTER: chal.emplace(ChallengeType::AFTER, ref->K()); break;
case Fragment::SHA256: chal.emplace(ChallengeType::SHA256, ChallengeNumber(ref->data)); break; case Fragment::SHA256: chal.emplace(ChallengeType::SHA256, ChallengeNumber(ref->Data())); break;
case Fragment::RIPEMD160: chal.emplace(ChallengeType::RIPEMD160, ChallengeNumber(ref->data)); break; case Fragment::RIPEMD160: chal.emplace(ChallengeType::RIPEMD160, ChallengeNumber(ref->Data())); break;
case Fragment::HASH256: chal.emplace(ChallengeType::HASH256, ChallengeNumber(ref->data)); break; case Fragment::HASH256: chal.emplace(ChallengeType::HASH256, ChallengeNumber(ref->Data())); break;
case Fragment::HASH160: chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->data)); break; case Fragment::HASH160: chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->Data())); break;
default: break; default: break;
} }
for (const auto& sub : ref->subs) { for (const auto& sub : ref->Subs()) {
stack.push_back(sub.get()); stack.push_back(sub.get());
} }
} }