Return P2WSH script pubkey for keyed anchor prevouts
What changed, and why it matters
This commit fixes a bug in how Lightning Dev Kit describes anchor outputs when preparing transactions for external wallets to sign. Previously, for a type of anchor tied to a specific channel key, the code returned the raw 'witness script' (the spending conditions) instead of the proper P2WSH address/script pubkey. Wallets use this data to identify and validate the coin being spent. Providing the wrong descriptor could cause wallets to reject the PSBT or, in worst cases, misidentify the output, potentially leading to invalid transactions or unsafe signing behavior. The fix converts the redeemscript to its P2WSH script pubkey, and adds a regression test.
Review and merge the patch. Ensure downstream wallets/signers that consume AnchorDescriptor::previous_utxo validate P2WSH script pubkeys correctly. Consider auditing other descriptor types for similar scriptPubKey vs witness script confusion.
Security signals we found
Incorrect scriptPubKey in PSBT witness_utxo metadata for anchor prevouts
Potential wallet/signer validation failure when signing fee-bumping transactions
Risk of misidentification of on-chain anchor output during CPFP/RBF bumping
Regression test added for keyed anchor P2WSH script pubkey
Discovered by external security review (Project Loupe)
Evidence from the diff
AnchorDescriptor::previous_utxo in lightning/src/events/bump_transaction/mod.rs is used for coin selection and to populate PSBT witness_utxo metadata. For ‘keyed anchors’ (non-zero-fee commitment anchors), the code previously returned the bare redeemscript produced by get_keyed_anchor_redeemscript. The patch appends .to_p2wsh() so the returned script_pubkey is the correct P2WSH output script. This aligns keyed anchors with shared anchors and with what PSBT signers/wallets expect. A unit test verifies the script_pubkey now matches the P2WSH of the keyed anchor redeemscript.
Changed components
lightning/src/events/bump_transaction/mod.rsAnchorDescriptor::previous_utxoKey anchor output handling in transaction bumpingInspect captured patch +24 / −0
diff --git a/lightning/src/events/bump_transaction/mod.rs b/lightning/src/events/bump_transaction/mod.rs
index 79f5ace..af2709c 100644
--- a/lightning/src/events/bump_transaction/mod.rs
+++ b/lightning/src/events/bump_transaction/mod.rs
@@ -64,6 +64,7 @@ impl AnchorDescriptor {
chan_utils::get_keyed_anchor_redeemscript(
&channel_params.broadcaster_pubkeys().funding_pubkey,
)
+ .to_p2wsh()
} else {
assert!(tx_params.channel_type_features.supports_anchor_zero_fee_commitments());
shared_anchor_script_pubkey()
@@ -1031,4 +1032,27 @@ mod tests {
1 /* witness items */ + 1 /* schnorr sig len */ + 64 /* schnorr sig */
);
}
+
+ #[test]
+ fn test_anchor_descriptor_previous_utxo_script_pubkey_uses_p2wsh() {
+ let mut transaction_parameters = ChannelTransactionParameters::test_dummy(42_000_000);
+ transaction_parameters.channel_type_features =
+ ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
+
+ let funding_pubkey = transaction_parameters.holder_pubkeys.funding_pubkey;
+ let expected_script_pubkey =
+ chan_utils::get_keyed_anchor_redeemscript(&funding_pubkey).to_p2wsh();
+
+ let anchor_descriptor = AnchorDescriptor {
+ channel_derivation_parameters: ChannelDerivationParameters {
+ value_satoshis: 42_000_000,
+ keys_id: [42; 32],
+ transaction_parameters,
+ },
+ outpoint: OutPoint::null(),
+ value: Amount::from_sat(ANCHOR_OUTPUT_VALUE_SATOSHI),
+ };
+
+ assert_eq!(anchor_descriptor.previous_utxo().script_pubkey, expected_script_pubkey);
+ }
}
Why this scored 44/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.