f51665bee7psbt: validate pubkeys in MuSig2 pubnonce/partial sig deserialization (tboy1337) Pull request description: The previous fix for invalid MuSig2 pubkeys (bitcoin/bitcoin#34010) only addressed the PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS field. However, the PSBT_IN_MUSIG2_PUB_NONCE and PSBT_IN_MUSIG2_PARTIAL_SIG fields also deserialize pubkeys without validation, which could lead to crashes when invalid pubkeys are processed. This commit adds validation to the DeserializeMuSig2ParticipantDataIdentifier function to ensure all pubkeys in MuSig2 pubnonce and partial signature fields are fully valid elliptic curve points. The fix: - Validates both aggregate and participant pubkeys in MuSig2 pubnonce and partial signature deserialization - Throws std::ios_base::failure with descriptive error messages for invalid pubkeys - Prevents potential crashes from invalid elliptic curve points - Maintains backward compatibility for valid PSBTs This completes the fix for issues [#33999](https://github.com/bitcoin/bitcoin/issues/33999) and [#34201](https://github.com/bitcoin/bitcoin/issues/34201). ACKs for top commit: rkrux: lgtm ACKf51665bee7w0xlt: ACKf51665bee7darosior: utACKf51665bee7Tree-SHA512: 8454d77a05aa003a3121b0a5975e8a000125ee0d62343bfa625a75db113358ba7a210ae0376ca1666957b7de7005e06e5a54c95170430ee5e9e1416719b8af53
Various test vectors
mainnet_alt.json
For easier testing the difficulty is maximally increased in the first (and only) retarget period, by producing blocks approximately 2 minutes apart.
The alternate mainnet chain was generated as follows:
- use faketime to set node clock to 2 minutes after genesis block
- mine a block using a CPU miner such as https://github.com/pooler/cpuminer
- restart node with a faketime 2 minutes later
for i in {1..2016}
do
t=$(( 1231006505 + $i * 120 ))
faketime "`date -d @$t +'%Y-%m-%d %H:%M:%S'`" \
bitcoind -connect=0 -nocheckpoints -stopatheight=$i
done
The CPU miner is kept running as follows:
./minerd -u ... -p ... -o http://127.0.0.1:8332 --no-stratum \
--coinbase-addr 1NQpH6Nf8QtR2HphLRcvuVqfhXBXsiWn8r \
--algo sha256d --no-longpoll --scantime 3 --retry-pause 1
The payout address is derived from first BIP32 test vector master key:
pkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/44h/0h/0h/<0;1>/*)#fkjtr0yn
It uses pkh() because tr() outputs at low heights are not spendable (unexpected-witness).
This makes each block deterministic except for its timestamp and nonce, which
are stored in mainnet_alt.json and used to reconstruct the chain without
having to redo the proof-of-work.
The timestamp was not kept constant because at difficulty 1 it's not sufficient to only grind the nonce. Grinding the extra_nonce or version field instead would have required additional (stratum) software. It would also make it more complicated to reconstruct the blocks in this test.
The getblocktemplate RPC code needs to be patched to ignore not being connected
to any peers, and to ignore the IBD status check.
On macOS use faketime "@$t" instead.