Change:
version with version 1.  Therefore, v2-capable servers MUST use compatible version negotiation unless they do not support version 1. <del> As version 1 support is more likely than version 2 support, a client SHOULD use QUIC version 1 for its original version unless it has out- of-band knowledge that the server supports version 2. </del> <ins> 4.1. Compatible version negotiation between versions 1 and 2 follow the same requirements in either direction.  This section uses the terms "original version" and "negotiated version" from QUIC-VN. If the server elects to send a Retry packet, it MUST do so using the original version. The server SHOULD start sending its Initial packets using the negotiated version as soon as it decides to change.  Note that the server might send some Initial packets using the original version. Once the client has processed a packet using the negotiated version, it SHOULD send subsequent Initial packets using that version.  The server MUST NOT discard its original version Initial receive keys until it successfully processes a packet with the negotiated version. Both endpoints MUST send Handshake or 1-RTT packets using the negotiated version.  An endpoint MUST drop packets using any other version.  Endpoints have no need to generate the keying material that would allow them to decrypt or authenticate these packets. If the server's version_information transport parameter does not contain a Chosen Version field equivalent to the version in the server's Handshake packet headers, the client MUST terminate the connection with a VERSION_NEGOTIATION_ERROR. The client MUST NOT send 0-RTT packets using the negotiated version, even after processing a packet of that version from the server. Servers can apply original version 0-RTT packets to a connection without additional considerations. </ins> 5.

Discussion:
and I could be persuaded that some of the choices made here are not the best.
Oops, I posted , which is almost exactly the same. My bad. The 0-RTT thing is one I might contest here. It is possible to accept 0-RTT if you have a compatible upgrade, but I'm not sure that you ever need it. The situations in which you can use 0-RTT without knowing what version is in use are few. All the client has to do is remember the negotiated version from last time and use that version.
I take it we've reached rough consensus that 0RTT has value, though no one will force MT to accept those packets. I'm going to merge this, and in a separate PR (taking text from )
It is necessary to specify how retry works when a compatible upgrade is used. The easiest way to specify this is to say that Retry can be sent in version 1, but the validation is performed as though a version 2 retry was sent. That's what I've seen implemented thus far.
Here's the relevant text in your PR (numbers mine) (1) A server SHOULD produce a Retry packet in the same version as the Initial packet that the Retry packet responds to. (2) Validation of the Retry exchange uses the logic of the final negotiated version, treating the Retry as if it were sent in that version. (3) This means that the version used for Retry is not authenticated, only that it occurred and the connection ID that was used. (1) I made it a MUST in the recent merge, to make it a bit easier for clients. (2) I'm not really sure what this means in the context of v1/v2 -- the logic is identical in both cases. Maybe this is something for the v1->vn text (pending) in the VN doc? But yeah, anything in the client hello, including the retry TPs, are processed syntactically as v1 but the content is used for v2 purposes. Do I understand the takeaway correctly? (3) This is a fair point to make, I guess: the Retry logic only ever measured that the CIDs matched. But, meh? The client changing the version between connection attempts would be strange, but legal and not obviously dangerous. If you think this sentence is valuable, I can add it.

Fine. Yeah, this was just a wording choice of mine. I do think that the validation is an important point to be clear on, lest people decide to skip it. I don't think that this can be part of the VN document at least as it stands as the Retry mechanism is version-specific and so any handling of it also needs to be. This is really just noting the limitations of the validation. I don't think that it has security consequences, particularly if the client enforces the requirement that Retry use the original version (which, presumably they are permitted to... by dropping the packet).
URL is going to introduce some considerations specific to v1. Nevertheless, I'm happy to write something down here.
We now have some implementation experience, and got interop between 2 implementations. That's great, but the process was difficult because the transition is somehow under specified. There was a lot of discussion as issues with the compatible version negotiation draft: These issues cannot be fully addressed in the compatible version negotiation draft, which has to be version independent. Instead, they need to be addressed in specific drafts. The V2 draft, for example, should specify exactly what happens during the version negotiation. My understanding is that when version negotiation succeeds, we will see something like: Client sends a first flight composed of Version 1 initial packets Server may send Version 1 initial packets containing acknowledgement, e.g., to manage losses of Initial packets At some point, the server will have received and parsed the transport parameters, and decided to upgrade to V2 After that point, server will send version 2 packets (Initial, Handshake, 1RTT) Client will receive version 2 packets and should be ready to process them before the negotiation completes The transport parameters will arrive in V2 handshake packets, after which the negotiation is done. There are quite a few potential issues that need resolution: 1) As explained above, in case of successful negotiation, the client expects the server to start sending V2 packets asap. Shall it ignore V1 packets as soon as it received V2 packets? Should in check version numbers in Initial packets, in a process similar to key updates? 2) If the client receives transport parameters on a version 2 packet, what shall it do if the chosen version is V1? 3) And vice versa?

4) If the server receives V2 handshake packets from the client, shall it conclude that the negotiation is successful? 5) In case of session resumption, does the client resume using V1 or V2? I think the answer to that question depends on the content of the "supported versions" list provided by the server. If it includes V2, then the server is ready to receive V2 packets. If the server is part of a server farm with partial deployment of V2, it should not say that V2 is ready. The answer may also depend on local conditions at the client. 6) If the client resumes using V1, it will send 0-RTT packets using V1. The server will receive these packets after the client's initial packets, and thus after receiving the transport parameters and completing the version upgrade. Should the server drop these packets? Or should it continue accept them until the handshake completes? 7) On the client side, there will be a delay between completing the negotiation and finalizing the handshake. The client may want to send 0-RTT packets during that interval. Shall it send those using V1 or V2?
The most literal answer to your question is, "of course all v1 can be interchanged with v2, since they're identical". But I'm going to answer the more interesting question of what precise questions a new version has to answer. AFAICT, in the v1->v2 case, (assuming all the support is present) there are four possible responses from the server: 1) a v2 Initial with ACK and/or ServerHello 2) a v1 Initial with ACK, followed by a v2 Initial with ServerHello 3) a v1 Retry (a v2 Retry would also be correct, but silly for the server to do things that way) 4) a v1 Initial with ACK, followed by nothing (because some of the client hello was lost) I believe this generalizes to all transitions v1->vn. So clearly the client can't draw any conclusions about the ultimate version until it sees the server hello, or a v2 packet of any kind. It can't fully authenticate the handshake until we get 1-RTT keys.

So to answer your questions: (1) yes, ignore v1 once you get v2 -- you don't need the Initial ACK anyway (2) and (3) if the chosen version in the TP doesn't match the QUIC header, this is a VN violation, no? Shouldn't this be handled in the VN draft? (4) I would think that any client packet with v2 and the correct keys would do the trick. (5) The two elements of this are the NEWTOKEN token and the TLS session ticket. The hard part here is that the contents of this are not in any version spec; if QUIC and TLS implementations put version specific things in there, then it won't work. IIUC in general the session ticket wouldn't include anything derived from the version-dependent HKDF labels, so it ought to work. (6) and (7) I believe the server has to handle v1 0RTT till the handshake is over, as it can't guarantee that 0RTT arriving after the 2nd flight was sent after that flight. The client could switch its 0RTT to v2 once negotiated -- I have no strong opinion if that complexity is worthwhile. I don't think putting these responses in a PR is the right move -- I'd like to clarify what properly should go in the VN draft and what should rest here.
Minor fix. In NAME example, ACK in V1 from the server is received by the client before any V2 packets. So, the client can handle it anyway.
This is probably a good idea. We can say that 0RTT belongs to the previous connection of V1. NAME If you agree, let's implement this and do interop.
We need to prohibit v2 Retry since a v1-only client cannot retry if v2 Retry is received.
When a client see V2 in a long header, it switches to V2 keys. This switch is allowed only once. After handshake is completed, the client checks if the version for keys and Chosen Version is the same.
OK, I will test the 0-RTT part internally first. There are timing issues in the server code, depending on whether the 0-RTT key is produced before the negotiation or after it.
NAME The idea for 0-RTT works perfectly on my local tests.

I will brush up the code tomorrow and set up a public server.
Thank you for this work. Can quic v2 server accept a v1 0-RTT packet via Compatible Version Negotiation? If I understand correctly, The says that "future versions will determine how to handle it." Even if the server accepts v1 packets as is, I would think the handling needs to be described in v2.
Developers are actually puzzled. See URL
Moving the discussion here, I think that 0-RTT is not as clear-cut as it seems. When doing a compatible upgrade from v1 to v2, a server makes the switch when it processes the ClientHello (that is, all Initial packets from the client to a first approximation). It is relatively easy for the server to make the switch cleanly at that point because it doesn't need to read any more Initial packets and all other packets will be v2 from then on. A client makes the switch based on seeing a v2 packet. It might receive some v1 Initial packets, but the one containing a ServerHello will be v2. If the client is sending 0-RTT packets, it might need to send them until it receives all of the Handshake packets from the server. That is, it might be some time. For a client in that state, it doesn't really make sense to switch to sending v2 0-RTT packets, but if it doesn't it will be intermixing transmission of v1 0-RTT packets and v2 Handshake packets. This is awkward because there is no clean cut-over. In my implementation, I also have to deal with stack integration issues that make installing the right 0-RTT keys difficult. I ultimately opted to just reject 0-RTT if there was a version change. The number of cases in which you might want to use 0-RTT and you don't already know what version the server wants to use are very limited. Basically, this only happens if you are doing 0-RTT across an upgrade of the server. Losing 0-RTT in that case seems tolerable.
The text reflects the consensus so far. I have to update my implementation to ensure that it follows these rules exactly, in particular for 0RTT, might add comments when that implementation is tested.