Skip to content

Commit 6d11c9c

Browse files
achow101darosior
andcommitted
descriptor: Add proper Clone function to miniscript::Node
Multipath descriptors requires performing a deep copy, so a Clone function that does that is added to miniscript::Node instead of the current shallow copy. Co-Authored-By: Antoine Poinsot <[email protected]>
1 parent 5691fa9 commit 6d11c9c

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/script/descriptor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ class MiniscriptDescriptor final : public DescriptorImpl
13531353
for (const auto& arg : m_pubkey_args) {
13541354
providers.push_back(arg->Clone());
13551355
}
1356-
return std::make_unique<MiniscriptDescriptor>(std::move(providers), miniscript::MakeNodeRef<uint32_t>(*m_node));
1356+
return std::make_unique<MiniscriptDescriptor>(std::move(providers), m_node->Clone());
13571357
}
13581358
};
13591359

@@ -2143,7 +2143,7 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
21432143
for (auto& pub : parser.m_keys) {
21442144
pubs.emplace_back(std::move(pub.at(i)));
21452145
}
2146-
ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs), node));
2146+
ret.emplace_back(std::make_unique<MiniscriptDescriptor>(std::move(pubs), node->Clone()));
21472147
}
21482148
return ret;
21492149
}

src/script/miniscript.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,20 @@ struct Node {
528528
}
529529
}
530530

531+
NodeRef<Key> Clone() const
532+
{
533+
// Use TreeEval() to avoid a stack-overflow due to recursion
534+
auto upfn = [](const Node& node, Span<NodeRef<Key>> children) {
535+
std::vector<NodeRef<Key>> new_subs;
536+
for (auto child = children.begin(); child != children.end(); ++child) {
537+
new_subs.emplace_back(std::move(*child));
538+
}
539+
// std::make_unique (and therefore MakeNodeRef) doesn't work on private constructors
540+
return std::unique_ptr<Node>{new Node{internal::NoDupCheck{}, node.m_script_ctx, node.fragment, std::move(new_subs), node.keys, node.data, node.k}};
541+
};
542+
return TreeEval<NodeRef<Key>>(upfn);
543+
}
544+
531545
private:
532546
//! Cached ops counts.
533547
const internal::Ops ops;
@@ -546,6 +560,11 @@ struct Node {
546560
//! for all subnodes as well.
547561
mutable std::optional<bool> has_duplicate_keys;
548562

563+
// Constructor which takes all of the data that a Node could possibly contain.
564+
// This is kept private as no valid fragment has all of these arguments.
565+
// Only used by Clone()
566+
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)
567+
: 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()) {}
549568

550569
//! Compute the length of the script for this miniscript (including children).
551570
size_t CalcScriptLen() const {

0 commit comments

Comments
 (0)