No fuzz target feeds V2Transport bytes that an honest peer would not send past the v2 key exchange. I add p2p_transport_v2_receive. It knows the keys of the transport it tests. It builds the input from arbitrary bytes and from the parts of a valid handshake: the peer key, garbage, the garbage terminator and encrypted packets, which may be corrupted. It feeds the input in pieces of arbitrary size. It reaches every v2 receive state and the failures on the way to them.
I ran it for about 13 minutes in total from an empty corpus, with libFuzzer and the address and undefined sanitizers, and it found no crash. Replaying the corpus gets both accepted and rejected messages out of the transport.
This is one of several PRs from a large audit of Bitcoin Core that I did with the help of LLM tools. The audit produced its evidence all at once, which is why the PRs arrive together. I understand each change fully and will answer review questions myself.