What changed, and why it matters
This small update teaches btcd's transaction-script parser to recognize a new Bitcoin output type called 'Pay-to-Anchor' (P2A). Without this change, the parser would treat P2A outputs as unsupported, which could cause btcd to reject or mishandle transactions that use this new output type. The patch also adds a safety check so that scripts without an associated address don't accidentally return a nil address. It is a forward-compatibility / robustness fix rather than a clear-cut vulnerability patch.
Treat as a compatibility/robustness improvement. Review whether any downstream code assumes Address() always returns non-nil, and verify P2A script parsing matches consensus rules. No urgent security response is indicated by the diff alone.
Security signals we found
New script type support added (Pay-to-Anchor / P2A)
Guard added against zero-length address slice in Address()
Potential for transaction parsing/relay differences if unsupported
No explicit security or CVE language in commit
Evidence from the diff
The commit adds PayToAnchorTy support to txscript.ParsePkScript and related helpers. It defines payToAnchorLen=4, includes PayToAnchorTy in isSupportedScriptType, and handles it in PkScript.Script(). It also hardens PkScript.Address() by returning an error when ExtractPkScriptAddrs yields zero addresses, preventing a potential nil-pointer return. The change aligns btcd with Bitcoin’s P2A soft-fork (BIP-related anchor outputs used in ephemeral anchors), ensuring the node/wallet can parse these scripts instead of failing with ErrUnsupportedScriptType.
Changed components
txscript/pkscript.goParsePkScriptisSupportedScriptTypePkScript.ScriptPkScript.AddressInspect captured patch +12 / −1
diff --git a/txscript/pkscript.go b/txscript/pkscript.go
index 4998f97..fce7024 100644
--- a/txscript/pkscript.go
+++ b/txscript/pkscript.go
@@ -51,6 +51,9 @@ const (
// witnessV1TaprootLen is the length of a P2TR script.
witnessV1TaprootLen = 34
+ // payToAnchorLen is the length of a P2A script.
+ payToAnchorLen = 4
+
// maxLen is the maximum script length supported by ParsePkScript.
maxLen = witnessV0ScriptHashLen
)
@@ -103,7 +106,7 @@ func ParsePkScript(pkScript []byte) (PkScript, error) {
func isSupportedScriptType(class ScriptClass) bool {
switch class {
case PubKeyHashTy, WitnessV0PubKeyHashTy, ScriptHashTy,
- WitnessV0ScriptHashTy, WitnessV1TaprootTy:
+ WitnessV0ScriptHashTy, WitnessV1TaprootTy, PayToAnchorTy:
return true
default:
return false
@@ -140,6 +143,10 @@ func (s PkScript) Script() []byte {
script = make([]byte, witnessV1TaprootLen)
copy(script, s.script[:witnessV1TaprootLen])
+ case PayToAnchorTy:
+ script = make([]byte, payToAnchorLen)
+ copy(script, s.script[:payToAnchorLen])
+
default:
// Unsupported script type.
return nil
@@ -155,6 +162,10 @@ func (s PkScript) Address(chainParams *chaincfg.Params) (btcutil.Address, error)
return nil, fmt.Errorf("unable to parse address: %v", err)
}
+ if len(addrs) == 0 {
+ return nil, fmt.Errorf("script does not have an associated address")
+ }
+
return addrs[0], nil
}
Why this scored 34/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.