node: expose Chain::isSighashRangeproofActive() (tip-based dynafed check)
What changed, and why it matters
This commit adds a small internal helper that lets the wallet ask the node whether a particular Elements feature (SIGHASH_RANGEPROOF) is active at the current chain tip. It is purely an exposure of existing chain-state information through a programming interface; it does not change consensus rules, transaction validation, or network behavior. There is no obvious security bug here.
No security action required. Review the follow-up wallet/RPC commits that consume this interface to ensure the default sighash selection logic is sound and does not produce non-standard or invalid signatures around activation boundaries.
Security signals we found
No memory safety issues visible in the diff
No change to consensus or mempool validation rules
Uses existing locking primitive cs_main consistent with surrounding code
Pure interface exposure of existing DeploymentActiveAfter check
Evidence from the diff
The patch adds a virtual method isSighashRangeproofActive() to the Chain interface and implements it in node/interfaces.cpp. The implementation takes cs_main, reads the active chain tip, and returns DeploymentActiveAfter(..., DEPLOYMENT_DYNA_FED). This mirrors the existing mempool standardness gate for SCRIPT_SIGHASH_RANGEPROOF. It is intended to be consumed by wallet/RPC code to choose the default pre-Taproot sighash. The change is additive (+15 lines), read-only with respect to chain state, and does not modify validation logic.
Changed components
src/interfaces/chain.hsrc/node/interfaces.cppInspect captured patch +15 / −0
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 4676ce5..565db75 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -208,6 +208,13 @@ public:
//! Check if transaction is RBF opt in.
virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0;
+ //! ELEMENTS: Check whether SIGHASH_RANGEPROOF is active for signing at the
+ //! current chain tip (i.e. dynafed, which enables SCRIPT_SIGHASH_RANGEPROOF,
+ //! is active). Used to decide the default pre-Taproot sighash so that we only
+ //! commit to output rangeproofs when doing so yields standard, valid
+ //! signatures.
+ virtual bool isSighashRangeproofActive() = 0;
+
//! Check if transaction is in mempool.
virtual bool isInMempool(const uint256& txid) = 0;
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index c6b9c4d..1c690ff 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -668,6 +668,14 @@ public:
LOCK(m_node.mempool->cs);
return IsRBFOptIn(tx, *m_node.mempool);
}
+ bool isSighashRangeproofActive() override
+ {
+ // Mirror the mempool standardness check in MemPoolAccept: dynafed being
+ // active after the current tip enables SCRIPT_SIGHASH_RANGEPROOF, which
+ // is what makes SIGHASH_RANGEPROOF signatures standard and valid.
+ LOCK(::cs_main);
+ return DeploymentActiveAfter(chainman().ActiveChain().Tip(), chainman(), Consensus::DEPLOYMENT_DYNA_FED);
+ }
bool isInMempool(const uint256& txid) override
{
if (!m_node.mempool) return false;
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.