Skip to content

elements-23.x: backports from master - #1595

Merged
tomt1664 merged 14 commits into
ElementsProject:elements-23.xfrom
tomt1664:elements-23.x
Sep 3, 2026
Merged

elements-23.x: backports from master#1595
tomt1664 merged 14 commits into
ElementsProject:elements-23.xfrom
tomt1664:elements-23.x

Conversation

@tomt1664

@tomt1664 tomt1664 commented Sep 2, 2026

Copy link
Copy Markdown
Member

No description provided.

…d rangeproofs

a9db3b1 Add startup warning for signed-blocks parent chain (Tom Trevethan)
246c5ab Add virtual desctructor to CChainParams (Tom Trevethan)
779e71f PAK enforcement on confidential nAsset (Tom Trevethan)
ffd91c0 PartiallySignedTransaction::SetupFromTx indexes vtxinwit checked (Tom Trevethan)
84a05e3 check pubkey validity in tweakfedpegscript to prevent assert failure (Tom Trevethan)
3a8dec1 Return error for psbt if explicit amounts/assets deleted (Tom Trevethan)
4e5ca94 Return error for invalid rangproof amounts (Tom Trevethan)

Pull request description:

  Fixes for a number of issues with RPC errors for invalid PSBTs and amounts/rangeproofs.

ACKs for top commit:
  delta1:
    ACK a9db3b1; tested locally

Tree-SHA512: bf35348a5fad30e0f1f2b3caa2ec35ec521b583155e97f3a5f2504a3d70b41677f215fc01b28ccd30706ff5a7d021afb74c110a2c8f270942f5cba344544a55d
CreateAssetSurjectionProof asserted on secp256k1_surjectionproof_generate
and _verify failure. A crafted PSET can supply unrelated tags/generators
with no known discrete-log relationship, causing generation to fail and the
assert to abort the process. Make these recoverable errors by returning
false.
BlindPSBT passed the blinding pubkey straight to CKey::ECDH, whose only
validation is an assert on the peer key, so a crafted off-curve pubkey
(reaching IsBlinded() but failing IsFullyValid()) aborted the process.
Mirror the non-PSET path and return BlindingStatus::INVALID_BLINDER when the
pubkey is not fully valid.
BlindPSBT dereferenced output.amount without a nullopt check. A crafted v0
PSET output (m_blinder_index set, amount absent) reached the blinding loop
and dereferenced a disengaged std::optional, which is undefined behaviour.
Refuse such outputs with BlindingStatus::INVALID_BLINDER.
NextBlockIsParameterTransition computed the approval threshold as
(epoch_length*4)/5, which floor-divides. For epoch lengths not divisible by
5 this is below the intended at-least-four-fifths rule, so a transition
could pass with fewer than 80% of the epoch's blocks voting for it.

Use the overflow-safe ceiling N - N/5 (== ceil(N*4/5)). This is a no-op for
epoch lengths divisible by 5 (the only currently deployed case) and only
corrects the under-approximation for non-divisible epoch lengths.
A dynafed header always serializes block_height as part of its identity
(CBlockHeader::Serialize/GetHash), independent of the legacy
-con_blockheightinheader option. Previously the height was only validated
in ContextualCheckBlockHeader and only reconstructed in
CBlockIndex/CDiskBlockIndex::GetBlockHeader when that option was on, so a
dynafed header with a mismatched height could be accepted, and a header
rebuilt from an accepted index no longer matched the accepted header's hash
when the option was off.

Validate and reconstruct block_height for all dynafed headers regardless of
the option. Non-dynafed headers keep the legacy option behaviour. This does
not change any consensus rule: the height was already part of every dynafed
header's hash.
…ueProof

A range-membership proof whose lower bound equalled the displayed PSET
amount was accepted even when the committed value was larger, because only
min_value was compared. Require both verified bounds to equal the claimed
amount so a proof can no longer understate an output's value.
An explicit 9-byte value (or a null field) passed the IsNull() check and
its buffer was then parsed as a 33-byte Pedersen commitment, reading past
the end. Require IsCommitment() on both the value and asset fields so the
parser's length precondition holds and the out-of-bounds read is avoided.
The raw-blind RPC path can reach SurjectOutput with an empty
surjection_targets vector (a zero-input tx with multiple blindable
outputs), which indexed element [0] of the empty vector and passed it to
secp256k1_surjectionproof_initialize, triggering undefined behaviour.
Reject empty target sets up front, matching the existing over-limit guard.
@tomt1664
tomt1664 marked this pull request as draft September 2, 2026 15:47
…TH_RANGEPROOF for pre-taproot signing

feb50a3 doc: release note for default rangeproof-committing sighash (Byron Hambly)
a1aacfa test: assert wallet default commits rangeproofs post-dynafed (Byron Hambly)
5ed683c bitcoin-tx: default to rangeproof-committing sighash via chain params (Byron Hambly)
f5e2b1f rpc: default raw signing to rangeproof-committing sighash when dynafed active (Byron Hambly)
ce342f5 wallet: default to rangeproof-committing sighash when dynafed active (Byron Hambly)
3587d77 chainparams: add SighashRangeproofActiveByParams() for offline gating (Byron Hambly)
be15b06 node: expose Chain::isSighashRangeproofActive() (tip-based dynafed check) (Byron Hambly)
6a531c2 script: add SIGHASH_ALL_WITH_RANGEPROOF and DefaultSighashType; strip rangeproof bit for Taproot signing (Byron Hambly)
529eaa1 test: ruff format for feature_sighash_rangeproof.py (Byron Hambly)

Pull request description:

  Pre-Taproot signatures using the historical SIGHASH_ALL default do not commit to output rangeproofs, leaving a witness malleability gap: an attacker can alter a transaction's rangeproofs without invalidating its signatures. This branch closes that gap by making signing default to SIGHASH_ALL | SIGHASH_RANGEPROOF on chains where dynafed is active, while leaving explicit user-supplied sighash types untouched and preserving the legacy default.

  Scope:

  - script: adds SIGHASH_ALL_WITH_RANGEPROOF and a DefaultSighashType() helper; strips the 0x40 bit for Taproot/Schnorr signing so the constant is a valid universal default.
  - node: exposes Chain::isSighashRangeproofActive() for a live tip-based dynafed check.
  - chainparams: adds SighashRangeproofActiveByParams() for chainstate-less gating (used by bitcoin-tx).
  - wallet + raw RPCs (signrawtransactionwithkey, signrawtransactionwithwallet, walletprocesspsbt, descriptorprocesspsbt) + - bitcoin-tx: default to the rangeproof-committing sighash when dynafed is active.
  - Adds unit and functional test coverage plus a release note.

ACKs for top commit:
  tomt1664:
    ACK feb50a3 tested locally

Tree-SHA512: acef900cd368cbe9c8e0f5a2082b953ba55fd8dd78bf02c0b99b27c71500e93fdcd3abff39f85681f88b98a86cf6be59fbdbb5fd4b679a8c142500bb17f117f9
…ive-fee-asset

rpc: expose effective fee asset
04aa60c build: add simplicity/cmr.c to src/CMakeLists.txt (Byron Hambly)
e15a625 Squashed 'src/simplicity/' changes from 49b96499a6..abede47eb8 (Byron Hambly)

Pull request description:

  Updates the simplicity subtree to abede47eb835f5d39568cc705cefe5bf9e6ee769 matching BlockstreamResearch/simplicity#348

ACKs for top commit:
  tomt1664:
    ACK 04aa60c tested locally

Tree-SHA512: 6e4b1a640398f8a3017bab2ea94704bb6166612b239069512e9fcb831cbac502a4efab4517ca9c54d39fdee731d9a1cce9374df4d16ee6f63ff23bb090d42c19
@tomt1664
tomt1664 marked this pull request as ready for review September 3, 2026 14:35
@tomt1664
tomt1664 requested a review from delta1 September 3, 2026 14:36
@tomt1664 tomt1664 changed the title Cherry-picks from master to 23.x elements-23.x: backports from master Sep 3, 2026

@delta1 delta1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f80fb30; tested locally

@tomt1664
tomt1664 merged commit 871781b into ElementsProject:elements-23.x Sep 3, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants