AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
High 70 Bitcoin

txscript: use finalOpcodeData for nested P2SH redeem script extraction

Public commit record

What the developer wrote

Authored by Olaoluwa Osuntokun

73/100 · Adequate
txscript: use finalOpcodeData for nested P2SH redeem script extraction

Both NewEngine and GetWitnessSigOpCount used sigScript[1:] (a raw byte
suffix of the scriptSig) to identify the candidate redeem script for
nested P2SH witness detection. GetPreciseSigOpCount and the existing
P2SH execution path already get the redeem script as the final pushed
element of the push-only scriptSig (via finalOpcodeData and
savedFirstStack[len-1] respectively). This commit consolidates the
nested-witness detection sites to use finalOpcodeData(0, scriptSig) so
all three places agree on what the redeem script is.

As a side effect of using the actual redeem script for detection, the
len(witness) != 0 precondition in NewEngine becomes redundant — the
redeem script's shape alone determines whether the spend is nested
witness, and verifyWitnessProgram already enforces the required
witness-stack shape downstream.
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context
The short version

What changed, and why it matters

This commit fixes how btcd recognizes 'nested' SegWit transactions wrapped inside older P2SH outputs. Previously, two code paths guessed the redeem script by taking a raw slice of the signature script starting at the second byte (sigScript[1:]). That shortcut can mis-identify the redeem script when the signature script has more than one data push or unusual encoding. The patch makes all three relevant code paths agree: the redeem script is the last data push in the signature script. It also removes the requirement that a witness stack must be present to treat an input as nested SegWit, and tightens the malleability check so the signature script must be exactly one canonical push of the witness program. A related change makes unknown future SegWit versions enforce a clean stack instead of silently disabling SegWit behavior.

Recommended action

Treat this as a consensus-critical bugfix and review for potential chain-split or transaction-acceptance divergence versus Bitcoin Core. Nodes should upgrade promptly, especially if running as part of a mining, wallet, or relay infrastructure. Verify that the new canonical-push check does not reject any transactions that Bitcoin Core accepts, and that the unknown-witness-version cleanstack behavior matches Core's policy/consensus rules.

Security signals we found

01

Nested P2SH witness detection previously relied on sigScript[1:], a raw byte suffix, which can diverge from the actual final pushed redeem script

02

Inconsistent redeem-script identification across NewEngine, GetWitnessSigOpCount, GetPreciseSigOpCount, and P2SH execution path

03

Malleability check for nested P2SH witness tightened: scriptSig must now be exactly one canonical push of the redeem script

04

Precondition len(witness) != 0 removed; witness presence no longer gates nested-P2SH-witness classification

05

Unknown witness program versions now enforce cleanstack/truthy result instead of deactivating SegWit behavior

06

New helper buildWitnessProgram centralizes witness-program extraction and validation

Risk score

Why this scored 70/100

Our methodology →
Potential impact 22/30
Exploitability 15/25
Stealth signal 10/15
Affected reach 12/15
Confidence 7/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.