What do you think of just generalising feature negotiation so it's comprehensive?
Suppose "VERSION 80000+" specifies:
initiator sends a VERSION message responder sends a VERSION message
after having both send and received a VERSION message specifying a version >= 80000, both nodes must specify FEATURE support by sending multiple FEATURE messages, then conclude with a VERACK.
after VERACK, messages must only be sent if the other node has already indicated support via a FEATURE message:
feature: PING
msg: PING, PONG
feature: BLOCK <ver>
msg: INV <block>
msg: GETDATA <block>
msg: GETBLOCKS
msg: GETHEADERS
msg: HEADERS (if version >=1)
msg: BLOCK
msg: NOTFOUND <block>
feature: TXRELAY
msg: INV <tx>
msg: GETDATA <tx>
msg: TX
msg: NOTFOUND <tx>
msg: FEEFILTER
feature: ADDR <ver>
msg: GETADDR
msg: ADDR
msg: ADDRV2 (if version >=2)
feature: COMPACTBLOCK <ver>
msg: SENDCMPCT, CMPCTBLOCK, GETBLOCKTXN, BLOCKTXN
feature: TXFILTER
msg: FILTERLOAD, FILTERADD, FILTERCLEAR, MERKLEBLOCK, MEMPOOL
feature: COMPACTFILTER
msg: GETCFILTERS, CFILTER, GETCFHEADERS, CFHEADERS, GETCFCHECKPT,
CFCHECKPT
feature: WTXIDRELAY
msg: INV <wtx>, GETDATA <wtx>
erlay might then be adding v1 for TXRELAY, eg; and DISABLETX is just not sending a TXRELAY feature announcement.
Not sure which was KISS principle points here: is doing it part way actually simpler?
[part of the idea is that you do "VERSION FEATURE... VERACK" and then after that you'll never see any unexpected messages, because both sides will know exactly what features the other side supports]