Skip to content

Commit 4f85b05

Browse files
committed
Merge bitcoin/bitcoin#31713: miniscript refactor: Remove unique_ptr-indirection
964c44c test(miniscript): Prove avoidance of stack overflow (Hodlinator) 198bbae refactor(miniscript): Destroy nodes one full subs-vector at a time (Hodlinator) 50cab85 refactor(miniscript): Remove NodeRef & MakeNodeRef() (Hodlinator) 15fb34d refactor(miniscript): Remove superfluous unique_ptr-indirection (Hodlinator) e55b23c refactor(miniscript): Remove Node::subs mutability (Hodlinator) c6f798b refactor(miniscript): Make fields non-const & private (Hodlinator) 22e4115 doc(miniscript): Remove mention of shared pointers (Hodlinator) Pull request description: Removes one level of unnecessary indirection, which was a change that originally [aided in finding one issue](bitcoin/bitcoin#30866 (review)) in #30866. Simplifies the code one step further than 09a1875 belonging to aforementioned PR. Also adds test which verifies resistance to stack overflow when it comes to `~Node()` and `Node::Clone()`. No observed difference when running benchmarks: ExpandDescriptor/WalletIsMineDescriptors/WalletIsMineMigratedDescriptors/WalletLoadingDescriptors. Followup to #30866. ACKs for top commit: achow101: ACK 964c44c darosior: Code review ACK 964c44c l0rinc: ACK 964c44c Tree-SHA512: 32927e8f0f916fb70372ffd110f7ec7207d9e7a099c21c0a7482a12e96593b673c339719f4ab166ad7c086dc43767315fc1742c5b236a3facc45c4cfeb5872e9
2 parents 5d27073 + 964c44c commit 4f85b05

File tree

4 files changed

+388
-336
lines changed

4 files changed

+388
-336
lines changed

src/script/descriptor.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,31 +1584,31 @@ class StringMaker {
15841584
class MiniscriptDescriptor final : public DescriptorImpl
15851585
{
15861586
private:
1587-
miniscript::NodeRef<uint32_t> m_node;
1587+
miniscript::Node<uint32_t> m_node;
15881588

15891589
protected:
15901590
std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript> scripts,
15911591
FlatSigningProvider& provider) const override
15921592
{
1593-
const auto script_ctx{m_node->GetMsCtx()};
1593+
const auto script_ctx{m_node.GetMsCtx()};
15941594
for (const auto& key : keys) {
15951595
if (miniscript::IsTapscript(script_ctx)) {
15961596
provider.pubkeys.emplace(Hash160(XOnlyPubKey{key}), key);
15971597
} else {
15981598
provider.pubkeys.emplace(key.GetID(), key);
15991599
}
16001600
}
1601-
return Vector(m_node->ToScript(ScriptMaker(keys, script_ctx)));
1601+
return Vector(m_node.ToScript(ScriptMaker(keys, script_ctx)));
16021602
}
16031603

16041604
public:
1605-
MiniscriptDescriptor(std::vector<std::unique_ptr<PubkeyProvider>> providers, miniscript::NodeRef<uint32_t> node)
1605+
MiniscriptDescriptor(std::vector<std::unique_ptr<PubkeyProvider>> providers, miniscript::Node<uint32_t>&& node)
16061606
: DescriptorImpl(std::move(providers), "?"), m_node(std::move(node))
16071607
{
16081608
// Traverse miniscript tree for unsafe use of older()
1609-
miniscript::ForEachNode(*m_node, [&](const miniscript::Node<uint32_t>& node) {
1610-
if (node.fragment == miniscript::Fragment::OLDER) {
1611-
const uint32_t raw = node.k;
1609+
miniscript::ForEachNode(m_node, [&](const miniscript::Node<uint32_t>& node) {
1610+
if (node.Fragment() == miniscript::Fragment::OLDER) {
1611+
const uint32_t raw = node.K();
16121612
const uint32_t value_part = raw & ~CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
16131613
if (value_part > CTxIn::SEQUENCE_LOCKTIME_MASK) {
16141614
const bool is_time_based = (raw & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) != 0;
@@ -1626,7 +1626,7 @@ class MiniscriptDescriptor final : public DescriptorImpl
16261626
const DescriptorCache* cache = nullptr) const override
16271627
{
16281628
bool has_priv_key{false};
1629-
auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type, cache), has_priv_key);
1629+
auto res = m_node.ToString(StringMaker(arg, m_pubkey_args, type, cache), has_priv_key);
16301630
if (res) out = *res;
16311631
if (type == StringType::PRIVATE) {
16321632
Assume(res.has_value());
@@ -1639,15 +1639,17 @@ class MiniscriptDescriptor final : public DescriptorImpl
16391639
bool IsSolvable() const override { return true; }
16401640
bool IsSingleType() const final { return true; }
16411641

1642-
std::optional<int64_t> ScriptSize() const override { return m_node->ScriptSize(); }
1642+
std::optional<int64_t> ScriptSize() const override { return m_node.ScriptSize(); }
16431643

1644-
std::optional<int64_t> MaxSatSize(bool) const override {
1644+
std::optional<int64_t> MaxSatSize(bool) const override
1645+
{
16451646
// For Miniscript we always assume high-R ECDSA signatures.
1646-
return m_node->GetWitnessSize();
1647+
return m_node.GetWitnessSize();
16471648
}
16481649

1649-
std::optional<int64_t> MaxSatisfactionElems() const override {
1650-
return m_node->GetStackSize();
1650+
std::optional<int64_t> MaxSatisfactionElems() const override
1651+
{
1652+
return m_node.GetStackSize();
16511653
}
16521654

16531655
std::unique_ptr<DescriptorImpl> Clone() const override
@@ -1657,7 +1659,7 @@ class MiniscriptDescriptor final : public DescriptorImpl
16571659
for (const auto& arg : m_pubkey_args) {
16581660
providers.push_back(arg->Clone());
16591661
}
1660-
return std::make_unique<MiniscriptDescriptor>(std::move(providers), m_node->Clone());
1662+
return std::make_unique<MiniscriptDescriptor>(std::move(providers), m_node.Clone());
16611663
}
16621664
};
16631665

@@ -2566,7 +2568,7 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
25662568
}
25672569
if (!node->IsSane() || node->IsNotSatisfiable()) {
25682570
// Try to find the first insane sub for better error reporting.
2569-
auto insane_node = node.get();
2571+
const auto* insane_node = &node.value();
25702572
if (const auto sub = node->FindInsaneSub()) insane_node = sub;
25712573
error = *insane_node->ToString(parser);
25722574
if (!insane_node->IsValid()) {
@@ -2575,7 +2577,7 @@ std::vector<std::unique_ptr<DescriptorImpl>> ParseScript(uint32_t& key_exp_index
25752577
error += " is not sane";
25762578
if (!insane_node->IsNonMalleable()) {
25772579
error += ": malleable witnesses exist";
2578-
} else if (insane_node == node.get() && !insane_node->NeedsSignature()) {
2580+
} else if (insane_node == &node.value() && !insane_node->NeedsSignature()) {
25792581
error += ": witnesses without signature exist";
25802582
} else if (!insane_node->CheckTimeLocksMix()) {
25812583
error += ": contains mixes of timelocks expressed in blocks and seconds";
@@ -2775,7 +2777,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
27752777
for (auto& key : parser.m_keys) {
27762778
keys.emplace_back(std::move(key.at(0)));
27772779
}
2778-
return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(node));
2780+
return std::make_unique<MiniscriptDescriptor>(std::move(keys), std::move(*node));
27792781
}
27802782
}
27812783

0 commit comments

Comments
 (0)