Implement QUICv2 in QUICHE.

This CL reflects draft-ietf-quic-v2-01, except for the version negotiation bits -- therefore, the enable flag is blocked by the VN bug.

There are a bunch of changes to line breaks, particularly in quic_framer, that I believe came from the recently updated code checkers. I'm ignoring some new code checks that suggest changes to existing code constructs -- perhaps we should address the defensive coding stuff in another CL.

Protected by FLAGS_quic_reloadable_flag_quic_enable_version_rfcv2.

PiperOrigin-RevId: 424961568
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 50bbfef..05bbdfe 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -57,8 +57,7 @@
 // |out_len|, respectively. The resulting expanded secret is returned.
 std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf,
                                      const std::vector<uint8_t>& secret,
-                                     const std::string& label,
-                                     size_t out_len) {
+                                     const std::string& label, size_t out_len) {
   bssl::ScopedCBB quic_hkdf_label;
   CBB inner_label;
   const char label_prefix[] = "tls13 ";
@@ -91,13 +90,23 @@
 
 }  // namespace
 
+const std::string getLabelForVersion(const ParsedQuicVersion& version,
+                                     const absl::string_view& predicate) {
+  static_assert(SupportedVersions().size() == 6u,
+                "Supported versions out of sync with HKDF labels");
+  if (version == ParsedQuicVersion::V2Draft01()) {
+    return absl::StrCat("quicv2 ", predicate);
+  } else {
+    return absl::StrCat("quic ", predicate);
+  }
+}
+
 void CryptoUtils::InitializeCrypterSecrets(
-    const EVP_MD* prf,
-    const std::vector<uint8_t>& pp_secret,
-    QuicCrypter* crypter) {
-  SetKeyAndIV(prf, pp_secret, crypter);
-  std::vector<uint8_t> header_protection_key =
-      GenerateHeaderProtectionKey(prf, pp_secret, crypter->GetKeySize());
+    const EVP_MD* prf, const std::vector<uint8_t>& pp_secret,
+    const ParsedQuicVersion& version, QuicCrypter* crypter) {
+  SetKeyAndIV(prf, pp_secret, version, crypter);
+  std::vector<uint8_t> header_protection_key = GenerateHeaderProtectionKey(
+      prf, pp_secret, version, crypter->GetKeySize());
   crypter->SetHeaderProtectionKey(
       absl::string_view(reinterpret_cast<char*>(header_protection_key.data()),
                         header_protection_key.size()));
@@ -105,11 +114,13 @@
 
 void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
                               const std::vector<uint8_t>& pp_secret,
+                              const ParsedQuicVersion& version,
                               QuicCrypter* crypter) {
   std::vector<uint8_t> key =
-      HkdfExpandLabel(prf, pp_secret, "quic key", crypter->GetKeySize());
-  std::vector<uint8_t> iv =
-      HkdfExpandLabel(prf, pp_secret, "quic iv", crypter->GetIVSize());
+      HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "key"),
+                      crypter->GetKeySize());
+  std::vector<uint8_t> iv = HkdfExpandLabel(
+      prf, pp_secret, getLabelForVersion(version, "iv"), crypter->GetIVSize());
   crypter->SetKey(
       absl::string_view(reinterpret_cast<char*>(key.data()), key.size()));
   crypter->SetIV(
@@ -117,16 +128,17 @@
 }
 
 std::vector<uint8_t> CryptoUtils::GenerateHeaderProtectionKey(
-    const EVP_MD* prf,
-    const std::vector<uint8_t>& pp_secret,
-    size_t out_len) {
-  return HkdfExpandLabel(prf, pp_secret, "quic hp", out_len);
+    const EVP_MD* prf, const std::vector<uint8_t>& pp_secret,
+    const ParsedQuicVersion& version, size_t out_len) {
+  return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"),
+                         out_len);
 }
 
 std::vector<uint8_t> CryptoUtils::GenerateNextKeyPhaseSecret(
-    const EVP_MD* prf,
+    const EVP_MD* prf, const ParsedQuicVersion& version,
     const std::vector<uint8_t>& current_secret) {
-  return HkdfExpandLabel(prf, current_secret, "quic ku", current_secret.size());
+  return HkdfExpandLabel(prf, current_secret, getLabelForVersion(version, "ku"),
+                         current_secret.size());
 }
 
 namespace {
@@ -138,6 +150,9 @@
 const uint8_t kRFCv1InitialSalt[] = {0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34,
                                      0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
                                      0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a};
+const uint8_t kV2Draft01InitialSalt[] = {
+    0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d,
+    0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3};
 
 // Salts used by deployed versions of QUIC. When introducing a new version,
 // generate a new salt by running `openssl rand -hex 20`.
@@ -154,9 +169,12 @@
 
 const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
                                      size_t* out_len) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync with initial encryption salts");
-  if (version == ParsedQuicVersion::RFCv1()) {
+  if (version == ParsedQuicVersion::V2Draft01()) {
+    *out_len = ABSL_ARRAYSIZE(kV2Draft01InitialSalt);
+    return kV2Draft01InitialSalt;
+  } else if (version == ParsedQuicVersion::RFCv1()) {
     *out_len = ABSL_ARRAYSIZE(kRFCv1InitialSalt);
     return kRFCv1InitialSalt;
   } else if (version == ParsedQuicVersion::Draft29()) {
@@ -191,6 +209,11 @@
                                            0xe3, 0x68, 0xc8, 0x4e};
 const uint8_t kRFCv1RetryIntegrityNonce[] = {
     0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb};
+const uint8_t kV2Draft01RetryIntegrityKey[] = {
+    0xba, 0x85, 0x8d, 0xc7, 0xb4, 0x3d, 0xe5, 0xdb,
+    0xf8, 0x76, 0x17, 0xff, 0x4a, 0xb2, 0x53, 0xdb};
+const uint8_t kV2Draft01RetryIntegrityNonce[] = {
+    0x14, 0x1b, 0x99, 0xc2, 0x39, 0xb0, 0x3e, 0x78, 0x5d, 0x6a, 0x2e, 0x9f};
 // Retry integrity key used by ParsedQuicVersion::ReservedForNegotiation().
 const uint8_t kReservedForNegotiationRetryIntegrityKey[] = {
     0xf2, 0xcd, 0x8f, 0xe0, 0x36, 0xd0, 0x25, 0x35,
@@ -204,13 +227,21 @@
 bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
                                   absl::string_view* key,
                                   absl::string_view* nonce) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync with retry integrity keys");
   if (!version.UsesTls()) {
     QUIC_BUG(quic_bug_10699_2)
         << "Attempted to get retry integrity keys for invalid version "
         << version;
     return false;
+  } else if (version == ParsedQuicVersion::V2Draft01()) {
+    *key = absl::string_view(
+        reinterpret_cast<const char*>(kV2Draft01RetryIntegrityKey),
+        ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityKey));
+    *nonce = absl::string_view(
+        reinterpret_cast<const char*>(kV2Draft01RetryIntegrityNonce),
+        ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityNonce));
+    return true;
   } else if (version == ParsedQuicVersion::RFCv1()) {
     *key = absl::string_view(
         reinterpret_cast<const char*>(kRFCv1RetryIntegrityKey),
@@ -291,20 +322,20 @@
   std::vector<uint8_t> encryption_secret = HkdfExpandLabel(
       hash, handshake_secret, encryption_label, EVP_MD_size(hash));
   crypters->encrypter = std::make_unique<Aes128GcmEncrypter>();
-  InitializeCrypterSecrets(hash, encryption_secret, crypters->encrypter.get());
+  InitializeCrypterSecrets(hash, encryption_secret, version,
+                           crypters->encrypter.get());
 
   std::vector<uint8_t> decryption_secret = HkdfExpandLabel(
       hash, handshake_secret, decryption_label, EVP_MD_size(hash));
   crypters->decrypter = std::make_unique<Aes128GcmDecrypter>();
-  InitializeCrypterSecrets(hash, decryption_secret, crypters->decrypter.get());
+  InitializeCrypterSecrets(hash, decryption_secret, version,
+                           crypters->decrypter.get());
 }
 
 // static
 bool CryptoUtils::ValidateRetryIntegrityTag(
-    ParsedQuicVersion version,
-    QuicConnectionId original_connection_id,
-    absl::string_view retry_without_tag,
-    absl::string_view integrity_tag) {
+    ParsedQuicVersion version, QuicConnectionId original_connection_id,
+    absl::string_view retry_without_tag, absl::string_view integrity_tag) {
   unsigned char computed_integrity_tag[kRetryIntegrityTagLength];
   if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) {
     QUIC_BUG(quic_bug_10699_4)
@@ -348,10 +379,8 @@
 }
 
 // static
-void CryptoUtils::GenerateNonce(QuicWallTime now,
-                                QuicRandom* random_generator,
-                                absl::string_view orbit,
-                                std::string* nonce) {
+void CryptoUtils::GenerateNonce(QuicWallTime now, QuicRandom* random_generator,
+                                absl::string_view orbit, std::string* nonce) {
   // a 4-byte timestamp + 28 random bytes.
   nonce->reserve(kNonceSize);
   nonce->resize(kNonceSize);
@@ -375,17 +404,13 @@
 }
 
 // static
-bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version,
-                             absl::string_view premaster_secret,
-                             QuicTag aead,
-                             absl::string_view client_nonce,
-                             absl::string_view server_nonce,
-                             absl::string_view pre_shared_key,
-                             const std::string& hkdf_input,
-                             Perspective perspective,
-                             Diversification diversification,
-                             CrypterPair* crypters,
-                             std::string* subkey_secret) {
+bool CryptoUtils::DeriveKeys(
+    const ParsedQuicVersion& version, absl::string_view premaster_secret,
+    QuicTag aead, absl::string_view client_nonce,
+    absl::string_view server_nonce, absl::string_view pre_shared_key,
+    const std::string& hkdf_input, Perspective perspective,
+    Diversification diversification, CrypterPair* crypters,
+    std::string* subkey_secret) {
   // If the connection is using PSK, concatenate it with the pre-master secret.
   std::unique_ptr<char[]> psk_premaster_secret;
   if (!pre_shared_key.empty()) {
@@ -573,8 +598,7 @@
 }
 
 QuicErrorCode CryptoUtils::ValidateClientHello(
-    const CryptoHandshakeMessage& client_hello,
-    ParsedQuicVersion version,
+    const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version,
     const ParsedQuicVersionVector& supported_versions,
     std::string* error_details) {
   if (client_hello.tag() != kCHLO) {
@@ -597,8 +621,7 @@
 }
 
 QuicErrorCode CryptoUtils::ValidateClientHelloVersion(
-    QuicVersionLabel client_version,
-    ParsedQuicVersion connection_version,
+    QuicVersionLabel client_version, ParsedQuicVersion connection_version,
     const ParsedQuicVersionVector& supported_versions,
     std::string* error_details) {
   if (client_version != CreateQuicVersionLabel(connection_version)) {
@@ -736,8 +759,7 @@
 
 // static
 std::string CryptoUtils::HashHandshakeMessage(
-    const CryptoHandshakeMessage& message,
-    Perspective /*perspective*/) {
+    const CryptoHandshakeMessage& message, Perspective /*perspective*/) {
   std::string output;
   const QuicData& serialized = message.GetSerialized();
   uint8_t digest[SHA256_DIGEST_LENGTH];
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h
index 8884f6f..fce6201 100644
--- a/quic/core/crypto/crypto_utils.h
+++ b/quic/core/crypto/crypto_utils.h
@@ -79,9 +79,11 @@
   // on the given QuicCrypter |*crypter|.
   // This follows the derivation described in section 7.3 of RFC 8446, except
   // with the label prefix in HKDF-Expand-Label changed from "tls13 " to "quic "
-  // as described in draft-ietf-quic-tls-14, section 5.1.
+  // as described in draft-ietf-quic-tls-14, section 5.1, or "quicv2 " as
+  // described in draft-ietf-quic-v2-01.
   static void InitializeCrypterSecrets(const EVP_MD* prf,
                                        const std::vector<uint8_t>& pp_secret,
+                                       const ParsedQuicVersion& version,
                                        QuicCrypter* crypter);
 
   // Derives the key and IV from the packet protection secret and sets those
@@ -90,17 +92,17 @@
   // called before using |crypter|.
   static void SetKeyAndIV(const EVP_MD* prf,
                           const std::vector<uint8_t>& pp_secret,
+                          const ParsedQuicVersion& version,
                           QuicCrypter* crypter);
 
   // Derives the header protection key from the packet protection secret.
   static std::vector<uint8_t> GenerateHeaderProtectionKey(
-      const EVP_MD* prf,
-      const std::vector<uint8_t>& pp_secret,
-      size_t out_len);
+      const EVP_MD* prf, const std::vector<uint8_t>& pp_secret,
+      const ParsedQuicVersion& version, size_t out_len);
 
   // Given a secret for key phase n, return the secret for phase n+1.
   static std::vector<uint8_t> GenerateNextKeyPhaseSecret(
-      const EVP_MD* prf,
+      const EVP_MD* prf, const ParsedQuicVersion& version,
       const std::vector<uint8_t>& current_secret);
 
   // IETF QUIC encrypts ENCRYPTION_INITIAL messages with a version-specific key
@@ -130,10 +132,8 @@
   //   <4 bytes> current time
   //   <8 bytes> |orbit| (or random if |orbit| is empty)
   //   <20 bytes> random
-  static void GenerateNonce(QuicWallTime now,
-                            QuicRandom* random_generator,
-                            absl::string_view orbit,
-                            std::string* nonce);
+  static void GenerateNonce(QuicWallTime now, QuicRandom* random_generator,
+                            absl::string_view orbit, std::string* nonce);
 
   // DeriveKeys populates |crypters->encrypter|, |crypters->decrypter|, and
   // |subkey_secret| (optional -- may be null) given the contents of
@@ -155,15 +155,12 @@
   // |SetDiversificationNonce| with a diversification nonce will be needed to
   // complete keying.
   static bool DeriveKeys(const ParsedQuicVersion& version,
-                         absl::string_view premaster_secret,
-                         QuicTag aead,
+                         absl::string_view premaster_secret, QuicTag aead,
                          absl::string_view client_nonce,
                          absl::string_view server_nonce,
                          absl::string_view pre_shared_key,
-                         const std::string& hkdf_input,
-                         Perspective perspective,
-                         Diversification diversification,
-                         CrypterPair* crypters,
+                         const std::string& hkdf_input, Perspective perspective,
+                         Diversification diversification, CrypterPair* crypters,
                          std::string* subkey_secret);
 
   // Computes the FNV-1a hash of the provided DER-encoded cert for use in the
@@ -199,8 +196,7 @@
   // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error
   // code and sets |error_details|.
   static QuicErrorCode ValidateClientHello(
-      const CryptoHandshakeMessage& client_hello,
-      ParsedQuicVersion version,
+      const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version,
       const ParsedQuicVersionVector& supported_versions,
       std::string* error_details);
 
@@ -212,8 +208,7 @@
   // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error
   // code and sets |error_details|.
   static QuicErrorCode ValidateClientHelloVersion(
-      QuicVersionLabel client_version,
-      ParsedQuicVersion connection_version,
+      QuicVersionLabel client_version, ParsedQuicVersion connection_version,
       const ParsedQuicVersionVector& supported_versions,
       std::string* error_details);
 
diff --git a/quic/core/crypto/crypto_utils_test.cc b/quic/core/crypto/crypto_utils_test.cc
index 251f136..df1546a 100644
--- a/quic/core/crypto/crypto_utils_test.cc
+++ b/quic/core/crypto/crypto_utils_test.cc
@@ -8,6 +8,7 @@
 
 #include "absl/base/macros.h"
 #include "absl/strings/escaping.h"
+#include "absl/strings/string_view.h"
 #include "quic/core/quic_utils.h"
 #include "quic/platform/api/quic_test.h"
 #include "quic/test_tools/quic_test_utils.h"
@@ -165,6 +166,48 @@
   EXPECT_FALSE(error_details.empty());
 }
 
+// Test that the library is using the correct labels for each version, and
+// therefore generating correct obfuscators, using the test vectors in appendix
+// A of each RFC or internet-draft.
+TEST_F(CryptoUtilsTest, ValidateCryptoLabels) {
+  // if the number of HTTP/3 QUIC versions has changed, we need to change the
+  // expected_keys hardcoded into this test. Regrettably, this is not a
+  // compile-time constant.
+  EXPECT_EQ(AllSupportedVersionsWithTls().size(), 3u);
+  const char draft_29_key[] = {// test vector from draft-ietf-quic-tls-29, A.1
+                               0x14, 0x9d, 0x0b, 0x16, 0x62, 0xab, 0x87, 0x1f,
+                               0xbe, 0x63, 0xc4, 0x9b, 0x5e, 0x65, 0x5a, 0x5d};
+  const char v1_key[] = {// test vector from RFC 9001, A.1
+                         0xcf, 0x3a, 0x53, 0x31, 0x65, 0x3c, 0x36, 0x4c,
+                         0x88, 0xf0, 0xf3, 0x79, 0xb6, 0x06, 0x7e, 0x37};
+  const char v2_01_key[] = {// test vector from draft-ietf-quic-v2-01
+                            0x15, 0xd5, 0xb4, 0xd9, 0xa2, 0xb8, 0x91, 0x6a,
+                            0xa3, 0x9b, 0x1b, 0xfe, 0x57, 0x4d, 0x2a, 0xad};
+  const char connection_id[] =  // test vector from both docs
+      {0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08};
+  const QuicConnectionId cid(connection_id, sizeof(connection_id));
+  const char* key_str;
+  size_t key_size;
+  for (const ParsedQuicVersion& version : AllSupportedVersionsWithTls()) {
+    if (version == ParsedQuicVersion::Draft29()) {
+      key_str = draft_29_key;
+      key_size = sizeof(draft_29_key);
+    } else if (version == ParsedQuicVersion::RFCv1()) {
+      key_str = v1_key;
+      key_size = sizeof(v1_key);
+    } else {  // draft-ietf-quic-v2-01
+      key_str = v2_01_key;
+      key_size = sizeof(v2_01_key);
+    }
+    const absl::string_view expected_key{key_str, key_size};
+
+    CrypterPair crypters;
+    CryptoUtils::CreateInitialObfuscators(Perspective::IS_SERVER, version, cid,
+                                          &crypters);
+    EXPECT_EQ(crypters.encrypter->GetKey(), expected_key);
+  }
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/core/handshaker_delegate_interface.h b/quic/core/handshaker_delegate_interface.h
index 1e47d16..7fbc5ae 100644
--- a/quic/core/handshaker_delegate_interface.h
+++ b/quic/core/handshaker_delegate_interface.h
@@ -7,6 +7,7 @@
 
 #include "quic/core/crypto/transport_parameters.h"
 #include "quic/core/quic_types.h"
+#include "quic/core/quic_versions.h"
 
 namespace quic {
 
@@ -21,15 +22,12 @@
   // Called when new decryption key of |level| is available. Returns true if
   // decrypter is set successfully, otherwise, returns false.
   virtual bool OnNewDecryptionKeyAvailable(
-      EncryptionLevel level,
-      std::unique_ptr<QuicDecrypter> decrypter,
-      bool set_alternative_decrypter,
-      bool latch_once_used) = 0;
+      EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter,
+      bool set_alternative_decrypter, bool latch_once_used) = 0;
 
   // Called when new encryption key of |level| is available.
   virtual void OnNewEncryptionKeyAvailable(
-      EncryptionLevel level,
-      std::unique_ptr<QuicEncrypter> encrypter) = 0;
+      EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) = 0;
 
   // Called to set default encryption level to |level|. Only used in QUIC
   // crypto.
@@ -68,8 +66,7 @@
   // On failure, returns a QuicErrorCode and saves a detailed error in
   // |error_details|.
   virtual QuicErrorCode ProcessTransportParameters(
-      const TransportParameters& params,
-      bool is_resumption,
+      const TransportParameters& params, bool is_resumption,
       std::string* error_details) = 0;
 
   // Called at the end of an handshake operation callback.
@@ -77,6 +74,10 @@
 
   // Whether a packet flusher is currently attached.
   virtual bool PacketFlusherAttached() const = 0;
+
+  // Get the QUIC version currently in use. tls_handshaker needs this to pass
+  // to crypto_utils to apply version-dependent HKDF labels.
+  virtual ParsedQuicVersion parsed_version() const = 0;
 };
 
 }  // namespace quic
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index aa1ef09..cf84969 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -485,8 +485,7 @@
     }
   }
 
-  void AddToCache(absl::string_view path,
-                  int response_code,
+  void AddToCache(absl::string_view path, int response_code,
                   absl::string_view body) {
     memory_cache_backend_.AddSimpleResponse(server_hostname_, path,
                                             response_code, body);
@@ -657,16 +656,14 @@
   }
 
   bool SendSynchronousRequestAndCheckResponse(
-      QuicTestClient* client,
-      const std::string& request,
+      QuicTestClient* client, const std::string& request,
       const std::string& expected_response) {
     std::string received_response = client->SendSynchronousRequest(request);
     return CheckResponse(client, received_response, expected_response);
   }
 
   bool SendSynchronousRequestAndCheckResponse(
-      const std::string& request,
-      const std::string& expected_response) {
+      const std::string& request, const std::string& expected_response) {
     return SendSynchronousRequestAndCheckResponse(client_.get(), request,
                                                   expected_response);
   }
@@ -844,8 +841,7 @@
 };
 
 // Run all end to end tests with all supported versions.
-INSTANTIATE_TEST_SUITE_P(EndToEndTests,
-                         EndToEndTest,
+INSTANTIATE_TEST_SUITE_P(EndToEndTests, EndToEndTest,
                          ::testing::ValuesIn(GetTestParams()),
                          ::testing::PrintToStringParamName());
 
@@ -3210,8 +3206,7 @@
 class DuplicatePacketWithSpoofedSelfAddressWriter
     : public QuicPacketWriterWrapper {
  public:
-  WriteResult WritePacket(const char* buffer,
-                          size_t buf_len,
+  WriteResult WritePacket(const char* buffer, size_t buf_len,
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override {
@@ -4385,13 +4380,10 @@
 class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream {
  public:
   ServerStreamWithErrorResponseBody(
-      QuicStreamId id,
-      QuicSpdySession* session,
+      QuicStreamId id, QuicSpdySession* session,
       QuicSimpleServerBackend* quic_simple_server_backend,
       std::string response_body)
-      : QuicSimpleServerStream(id,
-                               session,
-                               BIDIRECTIONAL,
+      : QuicSimpleServerStream(id, session, BIDIRECTIONAL,
                                quic_simple_server_backend),
         response_body_(std::move(response_body)) {}
 
@@ -4420,8 +4412,7 @@
   ~StreamWithErrorFactory() override = default;
 
   QuicSimpleServerStream* CreateStream(
-      QuicStreamId id,
-      QuicSpdySession* session,
+      QuicStreamId id, QuicSpdySession* session,
       QuicSimpleServerBackend* quic_simple_server_backend) override {
     return new ServerStreamWithErrorResponseBody(
         id, session, quic_simple_server_backend, response_body_);
@@ -4434,12 +4425,9 @@
 // A test server stream that drops all received body.
 class ServerStreamThatDropsBody : public QuicSimpleServerStream {
  public:
-  ServerStreamThatDropsBody(QuicStreamId id,
-                            QuicSpdySession* session,
+  ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session,
                             QuicSimpleServerBackend* quic_simple_server_backend)
-      : QuicSimpleServerStream(id,
-                               session,
-                               BIDIRECTIONAL,
+      : QuicSimpleServerStream(id, session, BIDIRECTIONAL,
                                quic_simple_server_backend) {}
 
   ~ServerStreamThatDropsBody() override = default;
@@ -4481,8 +4469,7 @@
   ~ServerStreamThatDropsBodyFactory() override = default;
 
   QuicSimpleServerStream* CreateStream(
-      QuicStreamId id,
-      QuicSpdySession* session,
+      QuicStreamId id, QuicSpdySession* session,
       QuicSimpleServerBackend* quic_simple_server_backend) override {
     return new ServerStreamThatDropsBody(id, session,
                                          quic_simple_server_backend);
@@ -4493,13 +4480,9 @@
 class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream {
  public:
   ServerStreamThatSendsHugeResponse(
-      QuicStreamId id,
-      QuicSpdySession* session,
-      QuicSimpleServerBackend* quic_simple_server_backend,
-      int64_t body_bytes)
-      : QuicSimpleServerStream(id,
-                               session,
-                               BIDIRECTIONAL,
+      QuicStreamId id, QuicSpdySession* session,
+      QuicSimpleServerBackend* quic_simple_server_backend, int64_t body_bytes)
+      : QuicSimpleServerStream(id, session, BIDIRECTIONAL,
                                quic_simple_server_backend),
         body_bytes_(body_bytes) {}
 
@@ -4529,8 +4512,7 @@
   ~ServerStreamThatSendsHugeResponseFactory() override = default;
 
   QuicSimpleServerStream* CreateStream(
-      QuicStreamId id,
-      QuicSpdySession* session,
+      QuicStreamId id, QuicSpdySession* session,
       QuicSimpleServerBackend* quic_simple_server_backend) override {
     return new ServerStreamThatSendsHugeResponse(
         id, session, quic_simple_server_backend, body_bytes_);
@@ -5255,8 +5237,7 @@
 // called.
 class PacketHoldingWriter : public QuicPacketWriterWrapper {
  public:
-  WriteResult WritePacket(const char* buffer,
-                          size_t buf_len,
+  WriteResult WritePacket(const char* buffer, size_t buf_len,
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override {
@@ -5710,8 +5691,7 @@
       : error_returned_(false), version_(version) {}
   ~BadShloPacketWriter() override {}
 
-  WriteResult WritePacket(const char* buffer,
-                          size_t buf_len,
+  WriteResult WritePacket(const char* buffer, size_t buf_len,
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           quic::PerPacketOptions* options) override {
@@ -5728,6 +5708,9 @@
   }
 
   bool TypeByteIsServerHello(uint8_t type_byte) {
+    if (version_.UsesV2PacketTypes()) {
+      return ((type_byte & 0x30) >> 4) == 3;
+    }
     if (version_.UsesQuicCrypto()) {
       // ENCRYPTION_ZERO_RTT packet.
       return ((type_byte & 0x30) >> 4) == 1;
@@ -5784,21 +5767,23 @@
 
 class BadShloPacketWriter2 : public QuicPacketWriterWrapper {
  public:
-  BadShloPacketWriter2() : error_returned_(false) {}
+  BadShloPacketWriter2(ParsedQuicVersion version)
+      : error_returned_(false), version_(version) {}
   ~BadShloPacketWriter2() override {}
 
-  WriteResult WritePacket(const char* buffer,
-                          size_t buf_len,
+  WriteResult WritePacket(const char* buffer, size_t buf_len,
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           quic::PerPacketOptions* options) override {
     const uint8_t type_byte = buffer[0];
-    if ((type_byte & FLAGS_LONG_HEADER) &&
-        (((type_byte & 0x30) >> 4) == 1 || (type_byte & 0x7F) == 0x7C)) {
-      QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet";
-      return WriteResult(WRITE_STATUS_OK, buf_len);
-    }
-    if (!error_returned_ && !(type_byte & FLAGS_LONG_HEADER)) {
+
+    if (type_byte & FLAGS_LONG_HEADER) {
+      if (((type_byte & 0x30 >> 4) == (version_.UsesV2PacketTypes() ? 2 : 1)) ||
+          ((type_byte & 0x7F) == 0x7C)) {
+        QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet";
+        return WriteResult(WRITE_STATUS_OK, buf_len);
+      }
+    } else if (!error_returned_) {
       QUIC_DVLOG(1) << "Return write error for short header packet";
       error_returned_ = true;
       return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE);
@@ -5809,6 +5794,7 @@
 
  private:
   bool error_returned_;
+  ParsedQuicVersion version_;
 };
 
 TEST_P(EndToEndTest, ForwardSecureConnectionClose) {
@@ -5839,7 +5825,7 @@
       dispatcher,
       // This causes the all server sent ZERO_RTT_PROTECTED packets to be
       // dropped, and first short header packet causes write error.
-      new BadShloPacketWriter2());
+      new BadShloPacketWriter2(version_));
   server_thread_->Resume();
   client_.reset(CreateQuicClient(client_writer_));
   EXPECT_EQ("", client_->SendSynchronousRequest("/foo"));
@@ -6028,8 +6014,7 @@
  public:
   explicit CopyingPacketWriter(int num_packets_to_copy)
       : num_packets_to_copy_(num_packets_to_copy) {}
-  WriteResult WritePacket(const char* buffer,
-                          size_t buf_len,
+  WriteResult WritePacket(const char* buffer, size_t buf_len,
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override {
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 393bfd8..053849f 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -184,19 +184,12 @@
   TestConnection(QuicConnectionId connection_id,
                  QuicSocketAddress initial_self_address,
                  QuicSocketAddress initial_peer_address,
-                 TestConnectionHelper* helper,
-                 TestAlarmFactory* alarm_factory,
-                 TestPacketWriter* writer,
-                 Perspective perspective,
+                 TestConnectionHelper* helper, TestAlarmFactory* alarm_factory,
+                 TestPacketWriter* writer, Perspective perspective,
                  ParsedQuicVersion version)
-      : QuicConnection(connection_id,
-                       initial_self_address,
-                       initial_peer_address,
-                       helper,
-                       alarm_factory,
-                       writer,
-                       /* owns_writer= */ false,
-                       perspective,
+      : QuicConnection(connection_id, initial_self_address,
+                       initial_peer_address, helper, alarm_factory, writer,
+                       /* owns_writer= */ false, perspective,
                        SupportedVersions(version)),
         notifier_(nullptr) {
     writer->set_perspective(perspective);
@@ -215,11 +208,9 @@
     QuicConnectionPeer::SetLossAlgorithm(this, loss_algorithm);
   }
 
-  void SendPacket(EncryptionLevel /*level*/,
-                  uint64_t packet_number,
+  void SendPacket(EncryptionLevel /*level*/, uint64_t packet_number,
                   std::unique_ptr<QuicPacket> packet,
-                  HasRetransmittableData retransmittable,
-                  bool has_ack,
+                  HasRetransmittableData retransmittable, bool has_ack,
                   bool has_pending_frames) {
     ScopedPacketFlusher flusher(this);
     char buffer[kMaxOutgoingPacketSize];
@@ -239,8 +230,7 @@
   }
 
   QuicConsumedData SaveAndSendStreamData(QuicStreamId id,
-                                         const struct iovec* iov,
-                                         int iov_count,
+                                         const struct iovec* iov, int iov_count,
                                          size_t total_length,
                                          QuicStreamOffset offset,
                                          StreamSendingState state) {
@@ -555,8 +545,7 @@
 
 // Run tests with combinations of {ParsedQuicVersion, AckResponse}.
 struct TestParams {
-  TestParams(ParsedQuicVersion version,
-             AckResponse ack_response,
+  TestParams(ParsedQuicVersion version, AckResponse ack_response,
              bool no_stop_waiting)
       : version(version),
         ack_response(ack_response),
@@ -609,30 +598,20 @@
  protected:
   QuicConnectionTest()
       : connection_id_(TestConnectionId()),
-        framer_(SupportedVersions(version()),
-                QuicTime::Zero(),
-                Perspective::IS_CLIENT,
-                connection_id_.length()),
+        framer_(SupportedVersions(version()), QuicTime::Zero(),
+                Perspective::IS_CLIENT, connection_id_.length()),
         send_algorithm_(new StrictMock<MockSendAlgorithm>),
         loss_algorithm_(new MockLossAlgorithm()),
         helper_(new TestConnectionHelper(&clock_, &random_generator_)),
         alarm_factory_(new TestAlarmFactory()),
-        peer_framer_(SupportedVersions(version()),
-                     QuicTime::Zero(),
-                     Perspective::IS_SERVER,
-                     connection_id_.length()),
-        peer_creator_(connection_id_,
-                      &peer_framer_,
+        peer_framer_(SupportedVersions(version()), QuicTime::Zero(),
+                     Perspective::IS_SERVER, connection_id_.length()),
+        peer_creator_(connection_id_, &peer_framer_,
                       /*delegate=*/nullptr),
         writer_(
             new TestPacketWriter(version(), &clock_, Perspective::IS_CLIENT)),
-        connection_(connection_id_,
-                    kSelfAddress,
-                    kPeerAddress,
-                    helper_.get(),
-                    alarm_factory_.get(),
-                    writer_.get(),
-                    Perspective::IS_CLIENT,
+        connection_(connection_id_, kSelfAddress, kPeerAddress, helper_.get(),
+                    alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT,
                     version()),
         creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
         manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
@@ -872,16 +851,14 @@
         QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now()));
   }
 
-  size_t ProcessFramePacketAtLevel(uint64_t number,
-                                   QuicFrame frame,
+  size_t ProcessFramePacketAtLevel(uint64_t number, QuicFrame frame,
                                    EncryptionLevel level) {
     QuicFrames frames;
     frames.push_back(frame);
     return ProcessFramesPacketAtLevel(number, frames, level);
   }
 
-  size_t ProcessFramesPacketAtLevel(uint64_t number,
-                                    const QuicFrames& frames,
+  size_t ProcessFramesPacketAtLevel(uint64_t number, const QuicFrames& frames,
                                     EncryptionLevel level) {
     QuicPacketHeader header = ConstructPacketHeader(number, level);
     // Set the correct encryption level and encrypter on peer_creator and
@@ -1025,8 +1002,7 @@
     return encrypted_length;
   }
 
-  size_t ProcessDataPacketAtLevel(uint64_t number,
-                                  bool has_stop_waiting,
+  size_t ProcessDataPacketAtLevel(uint64_t number, bool has_stop_waiting,
                                   EncryptionLevel level) {
     std::unique_ptr<QuicPacket> packet(
         ConstructDataPacket(number, has_stop_waiting, level));
@@ -1055,8 +1031,7 @@
         QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
   }
 
-  QuicByteCount SendStreamDataToPeer(QuicStreamId id,
-                                     absl::string_view data,
+  QuicByteCount SendStreamDataToPeer(QuicStreamId id, absl::string_view data,
                                      QuicStreamOffset offset,
                                      StreamSendingState state,
                                      QuicPacketNumber* last_packet) {
@@ -1084,8 +1059,7 @@
         .Times(AnyNumber());
   }
 
-  void SendRstStream(QuicStreamId id,
-                     QuicRstStreamErrorCode error,
+  void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error,
                      QuicStreamOffset bytes_written) {
     notifier_.WriteOrBufferRstStream(id, error, bytes_written);
     connection_.OnStreamReset(id, error);
@@ -10499,7 +10473,12 @@
     return;
   }
 
-  // These values come from draft-ietf-quic-tls Appendix A.4.
+  // These values come from draft-ietf-quic-v2 Appendix A.4.
+  uint8_t retry_packet_rfcv2[] = {
+      0xcf, 0x70, 0x9a, 0x50, 0xc4, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a,
+      0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1d, 0xc7, 0x11, 0x30,
+      0xcd, 0x1e, 0xd3, 0x9d, 0x6e, 0xfc, 0xee, 0x5c, 0x85, 0x80, 0x65, 0x01};
+  // These values come from RFC9001 Appendix A.4.
   uint8_t retry_packet_rfcv1[] = {
       0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a,
       0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x04, 0xa2, 0x65, 0xba,
@@ -10511,7 +10490,10 @@
 
   uint8_t* retry_packet;
   size_t retry_packet_length;
-  if (version() == ParsedQuicVersion::RFCv1()) {
+  if (version() == ParsedQuicVersion::V2Draft01()) {
+    retry_packet = retry_packet_rfcv2;
+    retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv2);
+  } else if (version() == ParsedQuicVersion::RFCv1()) {
     retry_packet = retry_packet_rfcv1;
     retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv1);
   } else if (version() == ParsedQuicVersion::Draft29()) {
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index ca4ae48..add5164 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -1521,7 +1521,7 @@
   dispatcher_->ProcessPacket(server_address_, client_address, received_packet);
 }
 
-static_assert(quic::SupportedVersions().size() == 5u,
+static_assert(quic::SupportedVersions().size() == 6u,
               "Please add new RejectDeprecatedVersion tests above this assert "
               "when deprecating versions");
 
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 7482050..90e3fbd 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -135,6 +135,8 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pacing_sender_bursts, false)
 // When true, set the initial congestion control window from connection options in QuicSentPacketManager rather than TcpCubicSenderBytes.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, true)
+// When true, support draft-ietf-quic-v2-01
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_2_draft_01, false)
 // When true, the B203 connection option causes the Bbr2Sender to ignore inflight_hi during PROBE_UP and increase it when the bytes delivered without loss are higher.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_ignore_inflight_hi_in_probe_up, true)
 // When true, the B205 connection option enables extra acked in STARTUP, and B204 adds new logic to decrease it whenever max bandwidth increases.
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 79ace5a..6d2d9c7 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -170,8 +170,7 @@
   }
 }
 
-QuicPacketNumberLength ReadAckPacketNumberLength(
-    uint8_t flags) {
+QuicPacketNumberLength ReadAckPacketNumberLength(uint8_t flags) {
   switch (flags & PACKET_FLAGS_8BYTE_PACKET) {
     case PACKET_FLAGS_8BYTE_PACKET:
       return PACKET_6BYTE_PACKET_NUMBER;
@@ -197,16 +196,17 @@
   return static_cast<QuicPacketNumberLength>((type & 0x03) + 1);
 }
 
-uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type) {
+uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type,
+                                    const ParsedQuicVersion& version) {
   switch (type) {
     case INITIAL:
-      return 0;
+      return version.UsesV2PacketTypes() ? (1 << 4) : 0;
     case ZERO_RTT_PROTECTED:
-      return 1 << 4;
+      return version.UsesV2PacketTypes() ? (2 << 4) : (1 << 4);
     case HANDSHAKE:
-      return 2 << 4;
+      return version.UsesV2PacketTypes() ? (3 << 4) : (2 << 4);
     case RETRY:
-      return 3 << 4;
+      return version.UsesV2PacketTypes() ? 0 : (3 << 4);
     case VERSION_NEGOTIATION:
       return 0xF0;  // Value does not matter
     default:
@@ -215,20 +215,23 @@
   }
 }
 
-bool GetLongHeaderType(uint8_t type, QuicLongHeaderType* long_header_type) {
+bool GetLongHeaderType(uint8_t type, const ParsedQuicVersion& version,
+                       QuicLongHeaderType* long_header_type) {
   QUICHE_DCHECK((type & FLAGS_LONG_HEADER));
   switch ((type & 0x30) >> 4) {
     case 0:
-      *long_header_type = INITIAL;
+      *long_header_type = version.UsesV2PacketTypes() ? RETRY : INITIAL;
       break;
     case 1:
-      *long_header_type = ZERO_RTT_PROTECTED;
+      *long_header_type =
+          version.UsesV2PacketTypes() ? INITIAL : ZERO_RTT_PROTECTED;
       break;
     case 2:
-      *long_header_type = HANDSHAKE;
+      *long_header_type =
+          version.UsesV2PacketTypes() ? ZERO_RTT_PROTECTED : HANDSHAKE;
       break;
     case 3:
-      *long_header_type = RETRY;
+      *long_header_type = version.UsesV2PacketTypes() ? HANDSHAKE : RETRY;
       break;
     default:
       QUIC_BUG(quic_bug_10850_4) << "Unreachable statement";
@@ -331,8 +334,7 @@
   return full_packet_number > 0 || version.HasIetfQuicFrames();
 }
 
-bool AppendIetfConnectionIds(bool version_flag,
-                             bool use_length_prefix,
+bool AppendIetfConnectionIds(bool version_flag, bool use_length_prefix,
                              QuicConnectionId destination_connection_id,
                              QuicConnectionId source_connection_id,
                              QuicDataWriter* writer) {
@@ -533,8 +535,7 @@
 
 // static
 size_t QuicFramer::GetConnectionCloseFrameSize(
-    QuicTransportVersion version,
-    const QuicConnectionCloseFrame& frame) {
+    QuicTransportVersion version, const QuicConnectionCloseFrame& frame) {
   if (!VersionHasIetfQuicFrames(version)) {
     // Not IETF QUIC, return Google QUIC CONNECTION CLOSE frame size.
     return kQuicFrameTypeSize + kQuicErrorCodeSize +
@@ -569,8 +570,7 @@
 
 // static
 size_t QuicFramer::GetWindowUpdateFrameSize(
-    QuicTransportVersion version,
-    const QuicWindowUpdateFrame& frame) {
+    QuicTransportVersion version, const QuicWindowUpdateFrame& frame) {
   if (!VersionHasIetfQuicFrames(version)) {
     return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize;
   }
@@ -599,8 +599,7 @@
 
 // static
 size_t QuicFramer::GetStreamsBlockedFrameSize(
-    QuicTransportVersion version,
-    const QuicStreamsBlockedFrame& frame) {
+    QuicTransportVersion version, const QuicStreamsBlockedFrame& frame) {
   if (!VersionHasIetfQuicFrames(version)) {
     QUIC_BUG(quic_bug_10850_10)
         << "In version " << version
@@ -658,8 +657,7 @@
 
 // static
 size_t QuicFramer::GetRetransmittableControlFrameSize(
-    QuicTransportVersion version,
-    const QuicFrame& frame) {
+    QuicTransportVersion version, const QuicFrame& frame) {
   switch (frame.type) {
     case PING_FRAME:
       // Ping has no payload.
@@ -793,11 +791,8 @@
 }
 
 size_t QuicFramer::GetSerializedFrameLength(
-    const QuicFrame& frame,
-    size_t free_bytes,
-    bool first_frame,
-    bool last_frame,
-    QuicPacketNumberLength packet_number_length) {
+    const QuicFrame& frame, size_t free_bytes, bool first_frame,
+    bool last_frame, QuicPacketNumberLength packet_number_length) {
   // Prevent a rare crash reported in b/19458523.
   if (frame.type == ACK_FRAME && frame.ack_frame == nullptr) {
     QUIC_BUG(quic_bug_10850_13)
@@ -887,8 +882,7 @@
 }
 
 size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
-                                   const QuicFrames& frames,
-                                   char* buffer,
+                                   const QuicFrames& frames, char* buffer,
                                    size_t packet_length,
                                    EncryptionLevel level) {
   QUIC_BUG_IF(quic_bug_12975_2,
@@ -1345,10 +1339,8 @@
 // static
 std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket(
     QuicConnectionId server_connection_id,
-    QuicConnectionId client_connection_id,
-    bool ietf_quic,
-    bool use_length_prefix,
-    const ParsedQuicVersionVector& versions) {
+    QuicConnectionId client_connection_id, bool ietf_quic,
+    bool use_length_prefix, const ParsedQuicVersionVector& versions) {
   QUIC_CODE_COUNT(quic_build_version_negotiation);
   if (use_length_prefix) {
     QUICHE_DCHECK(ietf_quic);
@@ -1420,8 +1412,7 @@
 // static
 std::unique_ptr<QuicEncryptedPacket>
 QuicFramer::BuildIetfVersionNegotiationPacket(
-    bool use_length_prefix,
-    QuicConnectionId server_connection_id,
+    bool use_length_prefix, QuicConnectionId server_connection_id,
     QuicConnectionId client_connection_id,
     const ParsedQuicVersionVector& versions) {
   QUIC_DVLOG(1) << "Building IETF version negotiation packet with"
@@ -1566,8 +1557,7 @@
 }
 
 bool QuicFramer::ProcessVersionNegotiationPacket(
-    QuicDataReader* reader,
-    const QuicPacketHeader& header) {
+    QuicDataReader* reader, const QuicPacketHeader& header) {
   QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
 
   QuicVersionNegotiationPacket packet(
@@ -1667,8 +1657,7 @@
 // If the IETF length field only spans part of the outer packet,
 // then there is a coalesced packet after this one.
 void QuicFramer::MaybeProcessCoalescedPacket(
-    const QuicDataReader& encrypted_reader,
-    uint64_t remaining_bytes_length,
+    const QuicDataReader& encrypted_reader, uint64_t remaining_bytes_length,
     const QuicPacketHeader& header) {
   if (header.remaining_packet_length >= remaining_bytes_length) {
     // There is no coalesced packet.
@@ -2221,7 +2210,7 @@
   if (header.version_flag) {
     type = static_cast<uint8_t>(
         FLAGS_LONG_HEADER | FLAGS_FIXED_BIT |
-        LongHeaderTypeToOnWireValue(header.long_packet_type) |
+        LongHeaderTypeToOnWireValue(header.long_packet_type, version_) |
         PacketNumberLengthToOnWireValue(header.packet_number_length));
   } else {
     type = static_cast<uint8_t>(
@@ -2357,8 +2346,7 @@
 
 uint64_t QuicFramer::CalculatePacketNumberFromWire(
     QuicPacketNumberLength packet_number_length,
-    QuicPacketNumber base_packet_number,
-    uint64_t packet_number) const {
+    QuicPacketNumber base_packet_number, uint64_t packet_number) const {
   // The new packet number might have wrapped to the next epoch, or
   // it might have reverse wrapped to the previous epoch, or it might
   // remain in the same epoch.  Select the packet number closest to the
@@ -2632,7 +2620,8 @@
           set_detailed_error("Fixed bit is 0 in long header.");
           return false;
         }
-        if (!GetLongHeaderType(type, &header->long_packet_type)) {
+        if (!GetLongHeaderType(type, header->version,
+                               &header->long_packet_type)) {
           set_detailed_error("Illegal long header type value.");
           return false;
         }
@@ -2690,14 +2679,11 @@
 
 // static
 bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
-    QuicDataReader* reader,
-    ParsedQuicVersion version,
-    Perspective perspective,
+    QuicDataReader* reader, ParsedQuicVersion version, Perspective perspective,
     bool should_update_expected_server_connection_id_length,
     uint8_t* expected_server_connection_id_length,
     uint8_t* destination_connection_id_length,
-    uint8_t* source_connection_id_length,
-    std::string* detailed_error) {
+    uint8_t* source_connection_id_length, std::string* detailed_error) {
   uint8_t connection_id_lengths_byte;
   if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
     *detailed_error = "Unable to read ConnectionId length.";
@@ -2880,10 +2866,8 @@
 }
 
 bool QuicFramer::ProcessAndCalculatePacketNumber(
-    QuicDataReader* reader,
-    QuicPacketNumberLength packet_number_length,
-    QuicPacketNumber base_packet_number,
-    uint64_t* packet_number) {
+    QuicDataReader* reader, QuicPacketNumberLength packet_number_length,
+    QuicPacketNumber base_packet_number, uint64_t* packet_number) {
   uint64_t wire_packet_number;
   if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) {
     return false;
@@ -3131,8 +3115,7 @@
 
 // static
 bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel(
-    uint64_t frame_type,
-    EncryptionLevel level) {
+    uint64_t frame_type, EncryptionLevel level) {
   switch (level) {
     case ENCRYPTION_INITIAL:
     case ENCRYPTION_HANDSHAKE:
@@ -3560,8 +3543,7 @@
 }
 }  // namespace
 
-bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader,
-                                    uint8_t frame_type,
+bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, uint8_t frame_type,
                                     QuicStreamFrame* frame) {
   uint8_t stream_flags = frame_type;
 
@@ -3748,12 +3730,12 @@
 
   // Determine the two lengths from the frame type: largest acked length,
   // ack block length.
-  const QuicPacketNumberLength ack_block_length = ReadAckPacketNumberLength(
-      ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
-                  kActBlockLengthOffset));
-  const QuicPacketNumberLength largest_acked_length = ReadAckPacketNumberLength(
-      ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
-                  kLargestAckedOffset));
+  const QuicPacketNumberLength ack_block_length =
+      ReadAckPacketNumberLength(ExtractBits(
+          frame_type, kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset));
+  const QuicPacketNumberLength largest_acked_length =
+      ReadAckPacketNumberLength(ExtractBits(
+          frame_type, kQuicSequenceNumberLengthNumBits, kLargestAckedOffset));
 
   uint64_t largest_acked;
   if (!reader->ReadBytesToUInt64(largest_acked_length, &largest_acked)) {
@@ -4364,11 +4346,9 @@
 
 // static
 absl::string_view QuicFramer::GetAssociatedDataFromEncryptedPacket(
-    QuicTransportVersion version,
-    const QuicEncryptedPacket& encrypted,
+    QuicTransportVersion version, const QuicEncryptedPacket& encrypted,
     QuicConnectionIdLength destination_connection_id_length,
-    QuicConnectionIdLength source_connection_id_length,
-    bool includes_version,
+    QuicConnectionIdLength source_connection_id_length, bool includes_version,
     bool includes_diversification_nonce,
     QuicPacketNumberLength packet_number_length,
     QuicVariableLengthIntegerLength retry_token_length_length,
@@ -4397,8 +4377,7 @@
 }
 
 void QuicFramer::SetAlternativeDecrypter(
-    EncryptionLevel level,
-    std::unique_ptr<QuicDecrypter> decrypter,
+    EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter,
     bool latch_once_used) {
   QUICHE_DCHECK_NE(level, decrypter_level_);
   QUICHE_DCHECK(!version_.KnowsWhichDecrypterToUse());
@@ -4523,10 +4502,8 @@
 }
 
 size_t QuicFramer::EncryptInPlace(EncryptionLevel level,
-                                  QuicPacketNumber packet_number,
-                                  size_t ad_len,
-                                  size_t total_len,
-                                  size_t buffer_len,
+                                  QuicPacketNumber packet_number, size_t ad_len,
+                                  size_t total_len, size_t buffer_len,
                                   char* buffer) {
   QUICHE_DCHECK(packet_number.IsInitialized());
   if (encrypter_[level] == nullptr) {
@@ -4568,10 +4545,8 @@
 
 }  // namespace
 
-bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level,
-                                       char* buffer,
-                                       size_t buffer_len,
-                                       size_t ad_len) {
+bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, char* buffer,
+                                       size_t buffer_len, size_t ad_len) {
   QuicDataReader buffer_reader(buffer, buffer_len);
   QuicDataWriter buffer_writer(buffer_len, buffer);
   // The sample starts 4 bytes after the start of the packet number.
@@ -4615,7 +4590,7 @@
   QuicLongHeaderType header_type;
   if (IsLongHeader(type_byte)) {
     bitmask = 0x0f;
-    if (!GetLongHeaderType(type_byte, &header_type)) {
+    if (!GetLongHeaderType(type_byte, version_, &header_type)) {
       return false;
     }
   }
@@ -4781,8 +4756,7 @@
 
 size_t QuicFramer::EncryptPayload(EncryptionLevel level,
                                   QuicPacketNumber packet_number,
-                                  const QuicPacket& packet,
-                                  char* buffer,
+                                  const QuicPacket& packet, char* buffer,
                                   size_t buffer_len) {
   QUICHE_DCHECK(packet_number.IsInitialized());
   if (encrypter_[level] == nullptr) {
@@ -4867,8 +4841,7 @@
                                 absl::string_view encrypted,
                                 absl::string_view associated_data,
                                 const QuicPacketHeader& header,
-                                char* decrypted_buffer,
-                                size_t buffer_length,
+                                char* decrypted_buffer, size_t buffer_length,
                                 size_t* decrypted_length,
                                 EncryptionLevel* decrypted_level) {
   if (!EncryptionLevelIsValid(decrypter_level_)) {
@@ -5100,8 +5073,7 @@
 }
 
 size_t QuicFramer::GetAckFrameSize(
-    const QuicAckFrame& ack,
-    QuicPacketNumberLength /*packet_number_length*/) {
+    const QuicAckFrame& ack, QuicPacketNumberLength /*packet_number_length*/) {
   QUICHE_DCHECK(!ack.packets.Empty());
   size_t ack_size = 0;
 
@@ -5141,8 +5113,7 @@
 }
 
 size_t QuicFramer::ComputeFrameLength(
-    const QuicFrame& frame,
-    bool last_frame_in_packet,
+    const QuicFrame& frame, bool last_frame_in_packet,
     QuicPacketNumberLength packet_number_length) {
   switch (frame.type) {
     case STREAM_FRAME:
@@ -5370,8 +5341,7 @@
 }
 
 // static
-bool QuicFramer::AppendStreamId(size_t stream_id_length,
-                                QuicStreamId stream_id,
+bool QuicFramer::AppendStreamId(size_t stream_id_length, QuicStreamId stream_id,
                                 QuicDataWriter* writer) {
   if (stream_id_length == 0 || stream_id_length > 4) {
     QUIC_BUG(quic_bug_10850_77)
@@ -5397,8 +5367,7 @@
 // static
 bool QuicFramer::AppendAckBlock(uint8_t gap,
                                 QuicPacketNumberLength length_length,
-                                uint64_t length,
-                                QuicDataWriter* writer) {
+                                uint64_t length, QuicDataWriter* writer) {
   if (length == 0) {
     if (!IsValidPacketNumberLength(length_length)) {
       QUIC_BUG(quic_bug_10850_79)
@@ -5976,8 +5945,7 @@
 }
 
 bool QuicFramer::AppendConnectionCloseFrame(
-    const QuicConnectionCloseFrame& frame,
-    QuicDataWriter* writer) {
+    const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) {
   if (VersionHasIetfQuicFrames(version_.transport_version)) {
     return AppendIetfConnectionCloseFrame(frame, writer);
   }
@@ -6084,8 +6052,7 @@
 }
 
 bool QuicFramer::IsVersionNegotiation(
-    const QuicPacketHeader& header,
-    bool packet_has_ietf_packet_header) const {
+    const QuicPacketHeader& header, bool packet_has_ietf_packet_header) const {
   if (!packet_has_ietf_packet_header &&
       perspective_ == Perspective::IS_CLIENT) {
     return header.version_flag;
@@ -6097,8 +6064,7 @@
 }
 
 bool QuicFramer::AppendIetfConnectionCloseFrame(
-    const QuicConnectionCloseFrame& frame,
-    QuicDataWriter* writer) {
+    const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) {
   if (frame.close_type != IETF_QUIC_TRANSPORT_CONNECTION_CLOSE &&
       frame.close_type != IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
     QUIC_BUG(quic_bug_10850_90)
@@ -6135,8 +6101,7 @@
 }
 
 bool QuicFramer::ProcessIetfConnectionCloseFrame(
-    QuicDataReader* reader,
-    QuicConnectionCloseType type,
+    QuicDataReader* reader, QuicConnectionCloseType type,
     QuicConnectionCloseFrame* frame) {
   frame->close_type = type;
 
@@ -6263,8 +6228,7 @@
 }
 
 bool QuicFramer::ProcessStopSendingFrame(
-    QuicDataReader* reader,
-    QuicStopSendingFrame* stop_sending_frame) {
+    QuicDataReader* reader, QuicStopSendingFrame* stop_sending_frame) {
   if (!ReadUint32FromVarint62(reader, IETF_STOP_SENDING,
                               &stop_sending_frame->stream_id)) {
     return false;
@@ -6281,8 +6245,7 @@
 }
 
 bool QuicFramer::AppendStopSendingFrame(
-    const QuicStopSendingFrame& stop_sending_frame,
-    QuicDataWriter* writer) {
+    const QuicStopSendingFrame& stop_sending_frame, QuicDataWriter* writer) {
   if (!writer->WriteVarInt62(stop_sending_frame.stream_id)) {
     set_detailed_error("Can not write stop sending stream id");
     return false;
@@ -6438,8 +6401,7 @@
 }
 
 bool QuicFramer::AppendNewConnectionIdFrame(
-    const QuicNewConnectionIdFrame& frame,
-    QuicDataWriter* writer) {
+    const QuicNewConnectionIdFrame& frame, QuicDataWriter* writer) {
   if (!writer->WriteVarInt62(frame.sequence_number)) {
     set_detailed_error("Can not write New Connection ID sequence number");
     return false;
@@ -6500,8 +6462,7 @@
 }
 
 bool QuicFramer::AppendRetireConnectionIdFrame(
-    const QuicRetireConnectionIdFrame& frame,
-    QuicDataWriter* writer) {
+    const QuicRetireConnectionIdFrame& frame, QuicDataWriter* writer) {
   if (!writer->WriteVarInt62(frame.sequence_number)) {
     set_detailed_error("Can not write Retire Connection ID sequence number");
     return false;
@@ -6510,8 +6471,7 @@
 }
 
 bool QuicFramer::ProcessRetireConnectionIdFrame(
-    QuicDataReader* reader,
-    QuicRetireConnectionIdFrame* frame) {
+    QuicDataReader* reader, QuicRetireConnectionIdFrame* frame) {
   if (!reader->ReadVarInt62(&frame->sequence_number)) {
     set_detailed_error(
         "Unable to read retire connection ID frame sequence number.");
@@ -6567,8 +6527,7 @@
 }
 
 uint8_t QuicFramer::GetIetfStreamFrameTypeByte(
-    const QuicStreamFrame& frame,
-    bool last_frame_in_packet) const {
+    const QuicStreamFrame& frame, bool last_frame_in_packet) const {
   QUICHE_DCHECK(VersionHasIetfQuicFrames(version_.transport_version));
   uint8_t type_byte = IETF_STREAM;
   if (!last_frame_in_packet) {
@@ -6662,14 +6621,10 @@
 
 // static
 QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic(
-    QuicDataReader* reader,
-    uint8_t* first_byte,
-    PacketHeaderFormat* format,
-    bool* version_present,
-    QuicVersionLabel* version_label,
+    QuicDataReader* reader, uint8_t* first_byte, PacketHeaderFormat* format,
+    bool* version_present, QuicVersionLabel* version_label,
     ParsedQuicVersion* parsed_version,
-    QuicConnectionId* destination_connection_id,
-    std::string* detailed_error) {
+    QuicConnectionId* destination_connection_id, std::string* detailed_error) {
   *format = GOOGLE_QUIC_PACKET;
   *version_present = (*first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0;
   uint8_t destination_connection_id_length = 0;
@@ -6696,10 +6651,8 @@
 const QuicVersionLabel kProxVersionLabel = 0x50524F58;  // "PROX"
 
 inline bool PacketHasLengthPrefixedConnectionIds(
-    const QuicDataReader& reader,
-    ParsedQuicVersion parsed_version,
-    QuicVersionLabel version_label,
-    uint8_t first_byte) {
+    const QuicDataReader& reader, ParsedQuicVersion parsed_version,
+    QuicVersionLabel version_label, uint8_t first_byte) {
   if (parsed_version.IsKnown()) {
     return parsed_version.HasLengthPrefixedConnectionIds();
   }
@@ -6733,12 +6686,9 @@
 }
 
 inline bool ParseLongHeaderConnectionIds(
-    QuicDataReader* reader,
-    bool has_length_prefix,
-    QuicVersionLabel version_label,
-    QuicConnectionId* destination_connection_id,
-    QuicConnectionId* source_connection_id,
-    std::string* detailed_error) {
+    QuicDataReader* reader, bool has_length_prefix,
+    QuicVersionLabel version_label, QuicConnectionId* destination_connection_id,
+    QuicConnectionId* source_connection_id, std::string* detailed_error) {
   if (has_length_prefix) {
     if (!reader->ReadLengthPrefixedConnectionId(destination_connection_id)) {
       *detailed_error = "Unable to read destination connection ID.";
@@ -6795,21 +6745,15 @@
 
 // static
 QuicErrorCode QuicFramer::ParsePublicHeader(
-    QuicDataReader* reader,
-    uint8_t expected_destination_connection_id_length,
-    bool ietf_format,
-    uint8_t* first_byte,
-    PacketHeaderFormat* format,
-    bool* version_present,
-    bool* has_length_prefix,
-    QuicVersionLabel* version_label,
-    ParsedQuicVersion* parsed_version,
+    QuicDataReader* reader, uint8_t expected_destination_connection_id_length,
+    bool ietf_format, uint8_t* first_byte, PacketHeaderFormat* format,
+    bool* version_present, bool* has_length_prefix,
+    QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version,
     QuicConnectionId* destination_connection_id,
     QuicConnectionId* source_connection_id,
     QuicLongHeaderType* long_packet_type,
     QuicVariableLengthIntegerLength* retry_token_length_length,
-    absl::string_view* retry_token,
-    std::string* detailed_error) {
+    absl::string_view* retry_token, std::string* detailed_error) {
   *version_present = false;
   *has_length_prefix = false;
   *version_label = 0;
@@ -6875,7 +6819,7 @@
   }
 
   // Parse long packet type.
-  if (!GetLongHeaderType(*first_byte, long_packet_type)) {
+  if (!GetLongHeaderType(*first_byte, *parsed_version, long_packet_type)) {
     *detailed_error = "Unable to parse long packet type.";
     return QUIC_INVALID_PACKET_HEADER;
   }
@@ -6903,8 +6847,7 @@
 
 // static
 bool QuicFramer::WriteClientVersionNegotiationProbePacket(
-    char* packet_bytes,
-    QuicByteCount packet_length,
+    char* packet_bytes, QuicByteCount packet_length,
     const char* destination_connection_id_bytes,
     uint8_t destination_connection_id_length) {
   if (packet_bytes == nullptr) {
@@ -6981,10 +6924,8 @@
 
 // static
 bool QuicFramer::ParseServerVersionNegotiationProbeResponse(
-    const char* packet_bytes,
-    QuicByteCount packet_length,
-    char* source_connection_id_bytes,
-    uint8_t* source_connection_id_length_out,
+    const char* packet_bytes, QuicByteCount packet_length,
+    char* source_connection_id_bytes, uint8_t* source_connection_id_length_out,
     std::string* detailed_error) {
   if (detailed_error == nullptr) {
     QUIC_BUG(quic_bug_10850_101) << "Invalid error_details";
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 28b7c20..207329c 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -105,10 +105,8 @@
   bool SetHeaderProtectionKey(absl::string_view /*key*/) override {
     return true;
   }
-  bool EncryptPacket(uint64_t packet_number,
-                     absl::string_view associated_data,
-                     absl::string_view plaintext,
-                     char* output,
+  bool EncryptPacket(uint64_t packet_number, absl::string_view associated_data,
+                     absl::string_view plaintext, char* output,
                      size_t* output_length,
                      size_t /*max_output_length*/) override {
     packet_number_ = QuicPacketNumber(packet_number);
@@ -162,10 +160,8 @@
   bool SetDiversificationNonce(const DiversificationNonce& /*key*/) override {
     return true;
   }
-  bool DecryptPacket(uint64_t packet_number,
-                     absl::string_view associated_data,
-                     absl::string_view ciphertext,
-                     char* output,
+  bool DecryptPacket(uint64_t packet_number, absl::string_view associated_data,
+                     absl::string_view ciphertext, char* output,
                      size_t* output_length,
                      size_t /*max_output_length*/) override {
     packet_number_ = QuicPacketNumber(packet_number);
@@ -197,9 +193,7 @@
 };
 
 std::unique_ptr<QuicEncryptedPacket> EncryptPacketWithTagAndPhase(
-    const QuicPacket& packet,
-    uint8_t tag,
-    bool phase) {
+    const QuicPacket& packet, uint8_t tag, bool phase) {
   std::string packet_data = std::string(packet.AsStringPiece());
   if (phase) {
     packet_data[0] |= FLAGS_KEY_PHASE_BIT;
@@ -692,9 +686,7 @@
         decrypter_(new test::TestDecrypter()),
         version_(GetParam()),
         start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
-        framer_(AllSupportedVersions(),
-                start_,
-                Perspective::IS_SERVER,
+        framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER,
                 kQuicDefaultConnectionIdLength) {
     framer_.set_version(version_);
     if (framer_.version().KnowsWhichDecrypterToUse()) {
@@ -726,6 +718,19 @@
     return (CreateQuicVersionLabel(version_) >> 8 * (3 - pos)) & 0xff;
   }
 
+  // Helper functions to take a v1 long header packet and make it v2. These are
+  // not needed for short header packets, but if sent, this function will exit
+  // cleanly. It needs to be called twice for coalesced packets (see references
+  // to length_of_first_coalesced_packet below for examples of how to do this).
+  inline void ReviseFirstByteByVersion(unsigned char packet_ietf[]) {
+    if (version_.UsesV2PacketTypes() && (packet_ietf[0] >= 0x80)) {
+      packet_ietf[0] = (packet_ietf[0] + 0x10) | 0xc0;
+    }
+  }
+  inline void ReviseFirstByteByVersion(PacketFragments& packet_ietf) {
+    ReviseFirstByteByVersion(&packet_ietf[0].fragment[0]);
+  }
+
   bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) {
     if (packet_number != encrypter_->packet_number_) {
       QUIC_LOG(ERROR) << "Encrypted incorrect packet number.  expected "
@@ -762,8 +767,7 @@
   }
 
   bool CheckDecryption(
-      const QuicEncryptedPacket& encrypted,
-      bool includes_version,
+      const QuicEncryptedPacket& encrypted, bool includes_version,
       bool includes_diversification_nonce,
       QuicConnectionIdLength destination_connection_id_length,
       QuicConnectionIdLength source_connection_id_length,
@@ -838,15 +842,13 @@
         }
       }
 
-      if (expected_error.empty())
-        continue;
+      if (expected_error.empty()) continue;
 
       CheckProcessingFails(*packet, i, expected_error, error_code);
     }
   }
 
-  void CheckProcessingFails(const QuicEncryptedPacket& packet,
-                            size_t len,
+  void CheckProcessingFails(const QuicEncryptedPacket& packet, size_t len,
                             std::string expected_error,
                             QuicErrorCode error_code) {
     QuicEncryptedPacket encrypted(packet.data(), len, false);
@@ -855,8 +857,7 @@
     EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
   }
 
-  void CheckProcessingFails(unsigned char* packet,
-                            size_t len,
+  void CheckProcessingFails(unsigned char* packet, size_t len,
                             std::string expected_error,
                             QuicErrorCode error_code) {
     QuicEncryptedPacket encrypted(AsChars(packet), len, false);
@@ -894,8 +895,7 @@
 
   // N starts at 1.
   QuicStreamId GetNthStreamid(QuicTransportVersion transport_version,
-                              Perspective perspective,
-                              bool bidirectional,
+                              Perspective perspective, bool bidirectional,
                               int n) {
     if (bidirectional) {
       return QuicUtils::GetFirstBidirectionalStreamId(transport_version,
@@ -931,8 +931,7 @@
       GetQuicVersionByte(3)
 
 // Run all framer tests with all supported versions of QUIC.
-INSTANTIATE_TEST_SUITE_P(QuicFramerTests,
-                         QuicFramerTest,
+INSTANTIATE_TEST_SUITE_P(QuicFramerTests, QuicFramerTest,
                          ::testing::ValuesIn(AllSupportedVersions()),
                          ::testing::PrintToStringParamName());
 
@@ -1273,6 +1272,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   }
@@ -1379,6 +1379,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   } else if (framer_.version().HasIetfInvariantHeader()) {
@@ -1669,6 +1670,7 @@
   };
   // clang-format on
 
+  ReviseFirstByteByVersion(packet49);
   PacketFragments& fragments =
       framer_.version().HasLongHeaderLengths()
           ? packet49
@@ -2970,6 +2972,7 @@
           ? VARIABLE_LENGTH_INTEGER_LENGTH_1
           : VARIABLE_LENGTH_INTEGER_LENGTH_0;
 
+  ReviseFirstByteByVersion(packet_ietf);
   PacketFragments& fragments =
       VersionHasIetfQuicFrames(framer_.transport_version())
           ? packet_ietf
@@ -6420,6 +6423,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().UsesTls()) {
+    ReviseFirstByteByVersion(packet_with_tag);
     p = packet_with_tag;
     p_length = ABSL_ARRAYSIZE(packet_with_tag);
   } else if (framer_.version().HasLongHeaderLengths()) {
@@ -7115,6 +7119,7 @@
   unsigned char* p = packet;
   size_t p_size = ABSL_ARRAYSIZE(packet);
   if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+    ReviseFirstByteByVersion(packet_ietf);
     p = packet_ietf;
     p_size = ABSL_ARRAYSIZE(packet_ietf);
   } else if (framer_.version().HasLongHeaderLengths()) {
@@ -13034,10 +13039,16 @@
       'R',  'L',  'D',  '?',
   };
   // clang-format on
+  const size_t first_packet_ietf_size = 46;
+  // If the first packet changes, the attempt to fix the first byte of the
+  // second packet will fail.
+  EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3);
 
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
+    ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -13157,6 +13168,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -13304,10 +13316,16 @@
       'R',  'L',  'D',  '?',
   };
   // clang-format on
+  const size_t first_packet_ietf_size = 46;
+  // If the first packet changes, the attempt to fix the first byte of the
+  // second packet will fail.
+  EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3);
 
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
+    ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -13415,6 +13433,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   } else if (framer_.version().HasIetfInvariantHeader()) {
@@ -13517,6 +13536,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   } else if (framer_.version().HasIetfInvariantHeader()) {
@@ -13677,10 +13697,15 @@
   };
   // clang-format on
   const size_t length_of_first_coalesced_packet = 46;
+  // If the first packet changes, the attempt to fix the first byte of the
+  // second packet will fail.
+  EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3);
 
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
+    ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -13844,10 +13869,16 @@
       'R',  'L',  'D',  '?',
   };
   // clang-format on
+  const size_t length_of_first_coalesced_packet = 46;
+  // If the first packet changes, the attempt to fix the first byte of the
+  // second packet will fail.
+  EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3);
 
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
+    ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -13949,10 +13980,16 @@
       // version would be here but we cut off the invalid coalesced header.
   };
   // clang-format on
+  const size_t length_of_first_coalesced_packet = 46;
+  // If the first packet changes, the attempt to fix the first byte of the
+  // second packet will fail.
+  EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3);
 
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasIetfQuicFrames()) {
+    ReviseFirstByteByVersion(packet_ietf);
+    ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]);
     p = packet_ietf;
     p_length = ABSL_ARRAYSIZE(packet_ietf);
   }
@@ -14180,6 +14217,7 @@
         QuicEncryptedPacket(AsChars(long_header_packet),
                             ABSL_ARRAYSIZE(long_header_packet), false)));
   } else {
+    ReviseFirstByteByVersion(long_header_packet_ietf);
     EXPECT_TRUE(framer_.ProcessPacket(
         QuicEncryptedPacket(AsChars(long_header_packet_ietf),
                             ABSL_ARRAYSIZE(long_header_packet_ietf), false)));
@@ -14708,9 +14746,11 @@
     0x00,
   };
   // clang-format on
+
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   }
@@ -14776,6 +14816,7 @@
   unsigned char* p = packet;
   size_t p_length = ABSL_ARRAYSIZE(packet);
   if (framer_.version().HasLongHeaderLengths()) {
+    ReviseFirstByteByVersion(packet49);
     p = packet49;
     p_length = ABSL_ARRAYSIZE(packet49);
   }
@@ -15615,6 +15656,7 @@
   };
   // clang-format on
 
+  ReviseFirstByteByVersion(packet);
   QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
 
   EXPECT_FALSE(framer_.ProcessPacket(encrypted));
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index d06e1fe..88ae992 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -312,6 +312,7 @@
                                            std::string* error_details) override;
   void OnHandshakeCallbackDone() override;
   bool PacketFlusherAttached() const override;
+  ParsedQuicVersion parsed_version() const override { return version(); }
 
   // Implement StreamDelegateInterface.
   void OnStreamError(QuicErrorCode error_code,
diff --git a/quic/core/quic_version_manager.cc b/quic/core/quic_version_manager.cc
index 13e590d..4a84797 100644
--- a/quic/core/quic_version_manager.cc
+++ b/quic/core/quic_version_manager.cc
@@ -36,9 +36,11 @@
 }
 
 void QuicVersionManager::MaybeRefilterSupportedVersions() {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
-  if (disable_version_rfcv1_ !=
+  if (enable_version_2_draft_01_ !=
+          GetQuicReloadableFlag(quic_enable_version_2_draft_01) ||
+      disable_version_rfcv1_ !=
           GetQuicReloadableFlag(quic_disable_version_rfcv1) ||
       disable_version_draft_29_ !=
           GetQuicReloadableFlag(quic_disable_version_draft_29) ||
@@ -48,6 +50,8 @@
           GetQuicReloadableFlag(quic_disable_version_q046) ||
       disable_version_q043_ !=
           GetQuicReloadableFlag(quic_disable_version_q043)) {
+    enable_version_2_draft_01_ =
+        GetQuicReloadableFlag(quic_enable_version_2_draft_01);
     disable_version_rfcv1_ = GetQuicReloadableFlag(quic_disable_version_rfcv1);
     disable_version_draft_29_ =
         GetQuicReloadableFlag(quic_disable_version_draft_29);
diff --git a/quic/core/quic_version_manager.h b/quic/core/quic_version_manager.h
index af44d34..44e134a 100644
--- a/quic/core/quic_version_manager.h
+++ b/quic/core/quic_version_manager.h
@@ -55,6 +55,8 @@
 
  private:
   // Cached value of reloadable flags.
+  // quic_enable_version_2_draft_01 flag
+  bool enable_version_2_draft_01_ = false;
   // quic_disable_version_rfcv1 flag
   bool disable_version_rfcv1_ = true;
   // quic_disable_version_draft_29 flag
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc
index 403009a..aa4581e 100644
--- a/quic/core/quic_version_manager_test.cc
+++ b/quic/core/quic_version_manager_test.cc
@@ -18,11 +18,12 @@
 class QuicVersionManagerTest : public QuicTest {};
 
 TEST_F(QuicVersionManagerTest, QuicVersionManager) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
     QuicEnableVersion(version);
   }
+  QuicDisableVersion(ParsedQuicVersion::V2Draft01());
   QuicDisableVersion(ParsedQuicVersion::RFCv1());
   QuicDisableVersion(ParsedQuicVersion::Draft29());
   QuicVersionManager manager(AllSupportedVersions());
@@ -65,6 +66,20 @@
             manager.GetSupportedVersionsWithOnlyHttp3());
   EXPECT_THAT(manager.GetSupportedAlpns(),
               ElementsAre("h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043"));
+
+  offset++;
+  QuicEnableVersion(ParsedQuicVersion::V2Draft01());
+  expected_parsed_versions.insert(expected_parsed_versions.begin(),
+                                  ParsedQuicVersion::V2Draft01());
+  EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions());
+  EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
+            manager.GetSupportedVersions());
+  EXPECT_EQ(3u, manager.GetSupportedVersionsWithOnlyHttp3().size());
+  EXPECT_EQ(CurrentSupportedHttp3Versions(),
+            manager.GetSupportedVersionsWithOnlyHttp3());
+  EXPECT_THAT(
+      manager.GetSupportedAlpns(),
+      ElementsAre("h3", "h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043"));
 }
 
 }  // namespace
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 4c9e661..63d21a1 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -42,11 +42,13 @@
 }
 
 void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
   const bool enable = should_enable;
   const bool disable = !should_enable;
-  if (version == ParsedQuicVersion::RFCv1()) {
+  if (version == ParsedQuicVersion::V2Draft01()) {
+    SetQuicReloadableFlag(quic_enable_version_2_draft_01, enable);
+  } else if (version == ParsedQuicVersion::RFCv1()) {
     SetQuicReloadableFlag(quic_disable_version_rfcv1, disable);
   } else if (version == ParsedQuicVersion::Draft29()) {
     SetQuicReloadableFlag(quic_disable_version_draft_29, disable);
@@ -182,6 +184,11 @@
   return handshake_protocol == PROTOCOL_QUIC_CRYPTO;
 }
 
+bool ParsedQuicVersion::UsesV2PacketTypes() const {
+  QUICHE_DCHECK(IsKnown());
+  return transport_version == QUIC_VERSION_IETF_2_DRAFT_01;
+}
+
 bool VersionHasLengthPrefixedConnectionIds(
     QuicTransportVersion transport_version) {
   QUICHE_DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED);
@@ -213,9 +220,11 @@
 }
 
 QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
-  if (parsed_version == ParsedQuicVersion::RFCv1()) {
+  if (parsed_version == ParsedQuicVersion::V2Draft01()) {
+    return MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4);
+  } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
     return MakeVersionLabel(0x00, 0x00, 0x00, 0x01);
   } else if (parsed_version == ParsedQuicVersion::Draft29()) {
     return MakeVersionLabel(0xff, 0x00, 0x00, 29);
@@ -411,10 +420,16 @@
 
 ParsedQuicVersionVector FilterSupportedVersions(
     ParsedQuicVersionVector versions) {
+  static_assert(SupportedVersions().size() == 6u,
+                "Supported versions out of sync");
   ParsedQuicVersionVector filtered_versions;
   filtered_versions.reserve(versions.size());
   for (const ParsedQuicVersion& version : versions) {
-    if (version == ParsedQuicVersion::RFCv1()) {
+    if (version == ParsedQuicVersion::V2Draft01()) {
+      if (GetQuicReloadableFlag(quic_enable_version_2_draft_01)) {
+        filtered_versions.push_back(version);
+      }
+    } else if (version == ParsedQuicVersion::RFCv1()) {
       if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) {
         filtered_versions.push_back(version);
       }
@@ -444,8 +459,7 @@
 }
 
 ParsedQuicVersionVector ParsedVersionOfIndex(
-    const ParsedQuicVersionVector& versions,
-    int index) {
+    const ParsedQuicVersionVector& versions, int index) {
   ParsedQuicVersionVector version;
   int version_count = versions.size();
   if (index >= 0 && index < version_count) {
@@ -461,8 +475,7 @@
 }
 
 std::string QuicVersionLabelVectorToString(
-    const QuicVersionLabelVector& version_labels,
-    const std::string& separator,
+    const QuicVersionLabelVector& version_labels, const std::string& separator,
     size_t skip_after_nth_version) {
   std::string result;
   for (size_t i = 0; i < version_labels.size(); ++i) {
@@ -490,6 +503,7 @@
     RETURN_STRING_LITERAL(QUIC_VERSION_50);
     RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_29);
     RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V1);
+    RETURN_STRING_LITERAL(QUIC_VERSION_IETF_2_DRAFT_01);
     RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED);
     RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION);
   }
@@ -508,10 +522,13 @@
 }
 
 std::string ParsedQuicVersionToString(ParsedQuicVersion version) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
   if (version == UnsupportedQuicVersion()) {
     return "0";
+  } else if (version == ParsedQuicVersion::V2Draft01()) {
+    QUICHE_DCHECK(version.UsesHttp3());
+    return "v2draft01";
   } else if (version == ParsedQuicVersion::RFCv1()) {
     QUICHE_DCHECK(version.UsesHttp3());
     return "RFCv1";
@@ -536,8 +553,7 @@
 }
 
 std::string ParsedQuicVersionVectorToString(
-    const ParsedQuicVersionVector& versions,
-    const std::string& separator,
+    const ParsedQuicVersionVector& versions, const std::string& separator,
     size_t skip_after_nth_version) {
   std::string result;
   for (size_t i = 0; i < versions.size(); ++i) {
@@ -604,7 +620,9 @@
 }
 
 std::string AlpnForVersion(ParsedQuicVersion parsed_version) {
-  if (parsed_version == ParsedQuicVersion::RFCv1()) {
+  if (parsed_version == ParsedQuicVersion::V2Draft01()) {
+    return "h3";
+  } else if (parsed_version == ParsedQuicVersion::RFCv1()) {
     return "h3";
   } else if (parsed_version == ParsedQuicVersion::Draft29()) {
     return "h3-29";
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index 331a99c..6c2144a 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -122,8 +122,9 @@
   // Number 70 used to represent draft-ietf-quic-transport-25.
   // Number 71 used to represent draft-ietf-quic-transport-27.
   // Number 72 used to represent draft-ietf-quic-transport-28.
-  QUIC_VERSION_IETF_DRAFT_29 = 73,  // draft-ietf-quic-transport-29.
-  QUIC_VERSION_IETF_RFC_V1 = 80,    // RFC 9000.
+  QUIC_VERSION_IETF_DRAFT_29 = 73,    // draft-ietf-quic-transport-29.
+  QUIC_VERSION_IETF_RFC_V1 = 80,      // RFC 9000.
+  QUIC_VERSION_IETF_2_DRAFT_01 = 81,  // draft-ietf-quic-v2-01.
   // Version 99 was a dumping ground for IETF QUIC changes which were not yet
   // ready for production between 2018-02 and 2020-02.
 
@@ -171,6 +172,7 @@
     QuicTransportVersion transport_version) {
   bool transport_version_is_valid = false;
   constexpr QuicTransportVersion valid_transport_versions[] = {
+      QUIC_VERSION_IETF_2_DRAFT_01,
       QUIC_VERSION_IETF_RFC_V1,
       QUIC_VERSION_IETF_DRAFT_29,
       QUIC_VERSION_50,
@@ -195,7 +197,8 @@
       return transport_version != QUIC_VERSION_UNSUPPORTED &&
              transport_version != QUIC_VERSION_RESERVED_FOR_NEGOTIATION &&
              transport_version != QUIC_VERSION_IETF_DRAFT_29 &&
-             transport_version != QUIC_VERSION_IETF_RFC_V1;
+             transport_version != QUIC_VERSION_IETF_RFC_V1 &&
+             transport_version != QUIC_VERSION_IETF_2_DRAFT_01;
     case PROTOCOL_TLS1_3:
       return transport_version != QUIC_VERSION_UNSUPPORTED &&
              transport_version != QUIC_VERSION_50 &&
@@ -245,6 +248,10 @@
            transport_version != other.transport_version;
   }
 
+  static constexpr ParsedQuicVersion V2Draft01() {
+    return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_2_DRAFT_01);
+  }
+
   static constexpr ParsedQuicVersion RFCv1() {
     return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_RFC_V1);
   }
@@ -361,6 +368,9 @@
 
   // Returns whether this version uses PROTOCOL_QUIC_CRYPTO.
   bool UsesQuicCrypto() const;
+
+  // Returns whether this version uses the QUICv2 Long Header Packet Types.
+  bool UsesV2PacketTypes() const;
 };
 
 QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
@@ -377,8 +387,7 @@
 using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>;
 
 QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-    std::ostream& os,
-    const ParsedQuicVersionVector& versions);
+    std::ostream& os, const ParsedQuicVersionVector& versions);
 
 // Representation of the on-the-wire QUIC version number. Will be written/read
 // to the wire in network-byte-order.
@@ -386,27 +395,25 @@
 using QuicVersionLabelVector = std::vector<QuicVersionLabel>;
 
 QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-    std::ostream& os,
-    const QuicVersionLabelVector& version_labels);
+    std::ostream& os, const QuicVersionLabelVector& version_labels);
 
 // This vector contains all crypto handshake protocols that are supported.
 constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() {
   return {PROTOCOL_TLS1_3, PROTOCOL_QUIC_CRYPTO};
 }
 
-constexpr std::array<ParsedQuicVersion, 5> SupportedVersions() {
+constexpr std::array<ParsedQuicVersion, 6> SupportedVersions() {
   return {
-      ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29(),
-      ParsedQuicVersion::Q050(),  ParsedQuicVersion::Q046(),
-      ParsedQuicVersion::Q043(),
+      ParsedQuicVersion::V2Draft01(), ParsedQuicVersion::RFCv1(),
+      ParsedQuicVersion::Draft29(),   ParsedQuicVersion::Q050(),
+      ParsedQuicVersion::Q046(),      ParsedQuicVersion::Q043(),
   };
 }
 
 using QuicTransportVersionVector = std::vector<QuicTransportVersion>;
 
 QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-    std::ostream& os,
-    const QuicTransportVersionVector& transport_versions);
+    std::ostream& os, const QuicTransportVersionVector& transport_versions);
 
 // Returns a vector of supported QUIC versions.
 QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions();
@@ -494,8 +501,7 @@
 // QuicVersionLabel values in the supplied |version_labels| vector. The values
 // after the (0-based) |skip_after_nth_version|'th are skipped.
 QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString(
-    const QuicVersionLabelVector& version_labels,
-    const std::string& separator,
+    const QuicVersionLabelVector& version_labels, const std::string& separator,
     size_t skip_after_nth_version);
 
 // Returns comma separated list of string representations of QuicVersionLabel
@@ -529,8 +535,7 @@
 // ParsedQuicVersion values in the supplied |versions| vector. The values after
 // the (0-based) |skip_after_nth_version|'th are skipped.
 QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString(
-    const ParsedQuicVersionVector& versions,
-    const std::string& separator,
+    const ParsedQuicVersionVector& versions, const std::string& separator,
     size_t skip_after_nth_version);
 
 // Returns comma separated list of string representations of ParsedQuicVersion
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc
index d60bd4d..6f384dd 100644
--- a/quic/core/quic_versions_test.cc
+++ b/quic/core/quic_versions_test.cc
@@ -120,9 +120,13 @@
             ParseQuicVersionLabel(MakeVersionLabel(0xff, 0x00, 0x00, 0x1d)));
   EXPECT_EQ(ParsedQuicVersion::RFCv1(),
             ParseQuicVersionLabel(MakeVersionLabel(0x00, 0x00, 0x00, 0x01)));
-  EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::RFCv1(),
+  EXPECT_EQ(ParsedQuicVersion::V2Draft01(),
+            ParseQuicVersionLabel(MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4)));
+  EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::V2Draft01(),
+                                     ParsedQuicVersion::RFCv1(),
                                      ParsedQuicVersion::Draft29()}),
             ParseQuicVersionLabelVector(QuicVersionLabelVector{
+                MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4),
                 MakeVersionLabel(0x00, 0x00, 0x00, 0x01),
                 MakeVersionLabel(0xaa, 0xaa, 0xaa, 0xaa),
                 MakeVersionLabel(0xff, 0x00, 0x00, 0x1d)}));
@@ -217,6 +221,8 @@
             CreateQuicVersionLabel(ParsedQuicVersion::Draft29()));
   EXPECT_EQ(MakeVersionLabel(0x00, 0x00, 0x00, 0x01),
             CreateQuicVersionLabel(ParsedQuicVersion::RFCv1()));
+  EXPECT_EQ(MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4),
+            CreateQuicVersionLabel(ParsedQuicVersion::V2Draft01()));
 
   // Make sure the negotiation reserved version is in the IETF reserved space.
   EXPECT_EQ(
@@ -291,6 +297,8 @@
   EXPECT_EQ("Q050", ParsedQuicVersionToString(ParsedQuicVersion::Q050()));
   EXPECT_EQ("draft29", ParsedQuicVersionToString(ParsedQuicVersion::Draft29()));
   EXPECT_EQ("RFCv1", ParsedQuicVersionToString(ParsedQuicVersion::RFCv1()));
+  EXPECT_EQ("v2draft01",
+            ParsedQuicVersionToString(ParsedQuicVersion::V2Draft01()));
 
   ParsedQuicVersionVector versions_vector = {ParsedQuicVersion::Q043()};
   EXPECT_EQ("Q043", ParsedQuicVersionVectorToString(versions_vector));
@@ -357,23 +365,25 @@
 // yet a typo was made in doing the #defines and it was caught
 // only in some test far removed from here... Better safe than sorry.
 TEST_F(QuicVersionsTest, CheckTransportVersionNumbersForTypos) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
   EXPECT_EQ(QUIC_VERSION_43, 43);
   EXPECT_EQ(QUIC_VERSION_46, 46);
   EXPECT_EQ(QUIC_VERSION_50, 50);
   EXPECT_EQ(QUIC_VERSION_IETF_DRAFT_29, 73);
   EXPECT_EQ(QUIC_VERSION_IETF_RFC_V1, 80);
+  EXPECT_EQ(QUIC_VERSION_IETF_2_DRAFT_01, 81);
 }
 
 TEST_F(QuicVersionsTest, AlpnForVersion) {
-  static_assert(SupportedVersions().size() == 5u,
+  static_assert(SupportedVersions().size() == 6u,
                 "Supported versions out of sync");
   EXPECT_EQ("h3-Q043", AlpnForVersion(ParsedQuicVersion::Q043()));
   EXPECT_EQ("h3-Q046", AlpnForVersion(ParsedQuicVersion::Q046()));
   EXPECT_EQ("h3-Q050", AlpnForVersion(ParsedQuicVersion::Q050()));
   EXPECT_EQ("h3-29", AlpnForVersion(ParsedQuicVersion::Draft29()));
   EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::RFCv1()));
+  EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::V2Draft01()));
 }
 
 TEST_F(QuicVersionsTest, QuicVersionEnabling) {
@@ -423,8 +433,12 @@
       EXPECT_NE(CreateQuicVersionLabel(version1),
                 CreateQuicVersionLabel(version2))
           << version1 << " " << version2;
-      EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2))
-          << version1 << " " << version2;
+      // The one pair where ALPNs are the same.
+      if ((version1 != ParsedQuicVersion::V2Draft01()) &&
+          (version2 != ParsedQuicVersion::RFCv1())) {
+        EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2))
+            << version1 << " " << version2;
+      }
     }
   }
 }
diff --git a/quic/core/tls_handshaker.cc b/quic/core/tls_handshaker.cc
index ad7dafb..2eee1cc 100644
--- a/quic/core/tls_handshaker.cc
+++ b/quic/core/tls_handshaker.cc
@@ -25,8 +25,7 @@
 TlsHandshaker::ProofVerifierCallbackImpl::~ProofVerifierCallbackImpl() {}
 
 void TlsHandshaker::ProofVerifierCallbackImpl::Run(
-    bool ok,
-    const std::string& /*error_details*/,
+    bool ok, const std::string& /*error_details*/,
     std::unique_ptr<ProofVerifyDetails>* details) {
   if (parent_ == nullptr) {
     return;
@@ -42,9 +41,7 @@
   parent_->AdvanceHandshake();
 }
 
-void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() {
-  parent_ = nullptr;
-}
+void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() { parent_ = nullptr; }
 
 TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream, QuicSession* session)
     : stream_(stream), handshaker_delegate_(session) {}
@@ -243,10 +240,13 @@
   std::unique_ptr<QuicEncrypter> encrypter =
       QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
   const EVP_MD* prf = Prf(cipher);
-  CryptoUtils::SetKeyAndIV(prf, write_secret, encrypter.get());
+  CryptoUtils::SetKeyAndIV(prf, write_secret,
+                           handshaker_delegate_->parsed_version(),
+                           encrypter.get());
   std::vector<uint8_t> header_protection_key =
-      CryptoUtils::GenerateHeaderProtectionKey(prf, write_secret,
-                                               encrypter->GetKeySize());
+      CryptoUtils::GenerateHeaderProtectionKey(
+          prf, write_secret, handshaker_delegate_->parsed_version(),
+          encrypter->GetKeySize());
   encrypter->SetHeaderProtectionKey(
       absl::string_view(reinterpret_cast<char*>(header_protection_key.data()),
                         header_protection_key.size()));
@@ -266,10 +266,13 @@
   std::unique_ptr<QuicDecrypter> decrypter =
       QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
   const EVP_MD* prf = Prf(cipher);
-  CryptoUtils::SetKeyAndIV(prf, read_secret, decrypter.get());
+  CryptoUtils::SetKeyAndIV(prf, read_secret,
+                           handshaker_delegate_->parsed_version(),
+                           decrypter.get());
   std::vector<uint8_t> header_protection_key =
-      CryptoUtils::GenerateHeaderProtectionKey(prf, read_secret,
-                                               decrypter->GetKeySize());
+      CryptoUtils::GenerateHeaderProtectionKey(
+          prf, read_secret, handshaker_delegate_->parsed_version(),
+          decrypter->GetKeySize());
   decrypter->SetHeaderProtectionKey(
       absl::string_view(reinterpret_cast<char*>(header_protection_key.data()),
                         header_protection_key.size()));
@@ -296,14 +299,16 @@
   }
   const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
   const EVP_MD* prf = Prf(cipher);
-  latest_read_secret_ =
-      CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_read_secret_);
-  latest_write_secret_ =
-      CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_write_secret_);
+  latest_read_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret(
+      prf, handshaker_delegate_->parsed_version(), latest_read_secret_);
+  latest_write_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret(
+      prf, handshaker_delegate_->parsed_version(), latest_write_secret_);
 
   std::unique_ptr<QuicDecrypter> decrypter =
       QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
-  CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, decrypter.get());
+  CryptoUtils::SetKeyAndIV(prf, latest_read_secret_,
+                           handshaker_delegate_->parsed_version(),
+                           decrypter.get());
   decrypter->SetHeaderProtectionKey(absl::string_view(
       reinterpret_cast<char*>(one_rtt_read_header_protection_key_.data()),
       one_rtt_read_header_protection_key_.size()));
@@ -322,7 +327,9 @@
   const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
   std::unique_ptr<QuicEncrypter> encrypter =
       QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher));
-  CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, encrypter.get());
+  CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_,
+                           handshaker_delegate_->parsed_version(),
+                           encrypter.get());
   encrypter->SetHeaderProtectionKey(absl::string_view(
       reinterpret_cast<char*>(one_rtt_write_header_protection_key_.data()),
       one_rtt_write_header_protection_key_.size()));