Repository: quic-go/quic-go
Pull request #4295 (2024-02-01 04:47:22)

protocol: rename VersionNumber to Version


Patch:
diff --git a/client.go b/client.go
index 634691ce..70dd5e19 100644
--- a/client.go
+++ b/client.go
@@ -28,7 +28,7 @@ type client struct {
 
 	initialPacketNumber  protocol.PacketNumber
 	hasNegotiatedVersion bool
-	version              protocol.VersionNumber
+	version              protocol.Version
 
 	handshakeChan chan struct{}
 
diff --git a/connection.go b/connection.go
index 0b3c6f1d..387268fe 100644
--- a/connection.go
+++ b/connection.go
@@ -25,7 +25,7 @@ import (
 )
 
 type unpacker interface {
-	UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.VersionNumber) (*unpackedPacket, error)
+	UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.Version) (*unpackedPacket, error)
 	UnpackShortHeader(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error)
 }
 
@@ -106,7 +106,7 @@ type closeError struct {
 
 type errCloseForRecreating struct {
 	nextPacketNumber protocol.PacketNumber
-	nextVersion      protocol.VersionNumber
+	nextVersion      protocol.Version
 }
 
 func (e *errCloseForRecreating) Error() string {
@@ -128,7 +128,7 @@ type connection struct {
 	srcConnIDLen int
 
 	perspective protocol.Perspective
-	version     protocol.VersionNumber
+	version     protocol.Version
 	config      *Config
 
 	conn      sendConn
@@ -236,7 +236,7 @@ var newConnection = func(
 	tracer *logging.ConnectionTracer,
 	tracingID uint64,
 	logger utils.Logger,
-	v protocol.VersionNumber,
+	v protocol.Version,
 ) quicConn {
 	s := &connection{
 		conn:                conn,
@@ -349,7 +349,7 @@ var newClientConnection = func(
 	tracer *logging.ConnectionTracer,
 	tracingID uint64,
 	logger utils.Logger,
-	v protocol.VersionNumber,
+	v protocol.Version,
 ) quicConn {
 	s := &connection{
 		conn:                conn,
@@ -1149,7 +1149,7 @@ func (s *connection) handleUnpackedLongHeaderPacket(
 	if !s.receivedFirstPacket {
 		s.receivedFirstPacket = true
 		if !s.versionNegotiated && s.tracer != nil && s.tracer.NegotiatedVersion != nil {
-			var clientVersions, serverVersions []protocol.VersionNumber
+			var clientVersions, serverVersions []protocol.Version
 			switch s.perspective {
 			case protocol.PerspectiveClient:
 				clientVersions = s.config.Versions
@@ -2383,7 +2383,7 @@ func (s *connection) getPerspective() protocol.Perspective {
 	return s.perspective
 }
 
-func (s *connection) GetVersion() protocol.VersionNumber {
+func (s *connection) GetVersion() protocol.Version {
 	return s.version
 }
 
diff --git a/framer.go b/framer.go
index d5c61bcf..df8c2841 100644
--- a/framer.go
+++ b/framer.go
@@ -15,10 +15,10 @@ type framer interface {
 	HasData() bool
 
 	QueueControlFrame(wire.Frame)
-	AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)
+	AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount)
 
 	AddActiveStream(protocol.StreamID)
-	AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)
+	AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount)
 
 	Handle0RTTRejection() error
 }
@@ -76,7 +76,7 @@ func (f *framerI) QueueControlFrame(frame wire.Frame) {
 	f.controlFrames = append(f.controlFrames, frame)
 }
 
-func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
+func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
 	f.controlFrameMutex.Lock()
 	defer f.controlFrameMutex.Unlock()
 
@@ -114,7 +114,7 @@ func (f *framerI) AddActiveStream(id protocol.StreamID) {
 	f.mutex.Unlock()
 }
 
-func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 	startLen := len(frames)
 	var length protocol.ByteCount
 	f.mutex.Lock()
diff --git a/fuzzing/header/cmd/corpus.go b/fuzzing/header/cmd/corpus.go
index 226dc106..ba53306f 100644
--- a/fuzzing/header/cmd/corpus.go
+++ b/fuzzing/header/cmd/corpus.go
@@ -20,9 +20,9 @@ func getRandomData(l int) []byte {
 }
 
 func getVNP(src, dest protocol.ArbitraryLenConnectionID, numVersions int) []byte {
-	versions := make([]protocol.VersionNumber, numVersions)
+	versions := make([]protocol.Version, numVersions)
 	for i := 0; i < numVersions; i++ {
-		versions[i] = protocol.VersionNumber(rand.Uint32())
+		versions[i] = protocol.Version(rand.Uint32())
 	}
 	return wire.ComposeVersionNegotiation(src, dest, versions)
 }
diff --git a/http3/client.go b/http3/client.go
index 9608f882..e6e3d68a 100644
--- a/http3/client.go
+++ b/http3/client.go
@@ -76,7 +76,7 @@ func newClient(hostname string, tlsConf *tls.Config, opts *roundTripperOpts, con
 	}
 	if len(conf.Versions) == 0 {
 		conf = conf.Clone()
-		conf.Versions = []quic.VersionNumber{protocol.SupportedVersions[0]}
+		conf.Versions = []quic.Version{protocol.SupportedVersions[0]}
 	}
 	if len(conf.Versions) != 1 {
 		return nil, errors.New("can only use a single QUIC version for dialing a HTTP/3 connection")
diff --git a/http3/server.go b/http3/server.go
index 769942c1..2d5437c9 100644
--- a/http3/server.go
+++ b/http3/server.go
@@ -55,7 +55,7 @@ type QUICEarlyListener interface {
 
 var _ QUICEarlyListener = &quic.EarlyListener{}
 
-func versionToALPN(v protocol.VersionNumber) string {
+func versionToALPN(v protocol.Version) string {
 	//nolint:exhaustive // These are all the versions we care about.
 	switch v {
 	case protocol.Version1, protocol.Version2:
@@ -77,7 +77,7 @@ func ConfigureTLSConfig(tlsConf *tls.Config) *tls.Config {
 			// determine the ALPN from the QUIC version used
 			proto := NextProtoH3
 			val := ch.Context().Value(quic.QUICVersionContextKey)
-			if v, ok := val.(quic.VersionNumber); ok {
+			if v, ok := val.(quic.Version); ok {
 				proto = versionToALPN(v)
 			}
 			config := tlsConf
diff --git a/interface.go b/interface.go
index 8741c48b..977fd22a 100644
--- a/interface.go
+++ b/interface.go
@@ -16,8 +16,12 @@ import (
 // The StreamID is the ID of a QUIC stream.
 type StreamID = protocol.StreamID
 
+// A Version is a QUIC version number.
+type Version = protocol.Version
+
 // A VersionNumber is a QUIC version number.
-type VersionNumber = protocol.VersionNumber
+// Deprecated: VersionNumber was renamed to Version.
+type VersionNumber = Version
 
 const (
 	// Version1 is RFC 9000
@@ -255,7 +259,7 @@ type Config struct {
 	GetConfigForClient func(info *ClientHelloInfo) (*Config, error)
 	// The QUIC versions that can be negotiated.
 	// If not set, it uses all versions available.
-	Versions []VersionNumber
+	Versions []Version
 	// HandshakeIdleTimeout is the idle timeout before completion of the handshake.
 	// If we don't receive any packet from the peer within this time, the connection attempt is aborted.
 	// Additionally, if the handshake doesn't complete in twice this time, the connection attempt is also aborted.
@@ -342,7 +346,7 @@ type ConnectionState struct {
 	// Used0RTT says if 0-RTT resumption was used.
 	Used0RTT bool
 	// Version is the QUIC version of the QUIC connection.
-	Version VersionNumber
+	Version Version
 	// GSO says if generic segmentation offload is used
 	GSO bool
 }
diff --git a/internal/handshake/aead.go b/internal/handshake/aead.go
index 6ab267a3..693939ae 100644
--- a/internal/handshake/aead.go
+++ b/internal/handshake/aead.go
@@ -7,7 +7,7 @@ import (
 	"github.com/quic-go/quic-go/internal/protocol"
 )
 
-func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.VersionNumber) cipher.AEAD {
+func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) cipher.AEAD {
 	keyLabel := hkdfLabelKeyV1
 	ivLabel := hkdfLabelIVV1
 	if v == protocol.Version2 {
diff --git a/internal/handshake/crypto_setup.go b/internal/handshake/crypto_setup.go
index 84296875..adf74fe7 100644
--- a/internal/handshake/crypto_setup.go
+++ b/internal/handshake/crypto_setup.go
@@ -32,7 +32,7 @@ type cryptoSetup struct {
 
 	events []Event
 
-	version protocol.VersionNumber
+	version protocol.Version
 
 	ourParams  *wire.TransportParameters
 	peerParams *wire.TransportParameters
@@ -76,7 +76,7 @@ func NewCryptoSetupClient(
 	rttStats *utils.RTTStats,
 	tracer *logging.ConnectionTracer,
 	logger utils.Logger,
-	version protocol.VersionNumber,
+	version protocol.Version,
 ) CryptoSetup {
 	cs := newCryptoSetup(
 		connID,
@@ -111,7 +111,7 @@ func NewCryptoSetupServer(
 	rttStats *utils.RTTStats,
 	tracer *logging.ConnectionTracer,
 	logger utils.Logger,
-	version protocol.VersionNumber,
+	version protocol.Version,
 ) CryptoSetup {
 	cs := newCryptoSetup(
 		connID,
@@ -169,7 +169,7 @@ func newCryptoSetup(
 	tracer *logging.ConnectionTracer,
 	logger utils.Logger,
 	perspective protocol.Perspective,
-	version protocol.VersionNumber,
+	version protocol.Version,
 ) *cryptoSetup {
 	initialSealer, initialOpener := NewInitialAEAD(connID, perspective, version)
 	if tracer != nil && tracer.UpdatedKeyFromTLS != nil {
diff --git a/internal/handshake/header_protector.go b/internal/handshake/header_protector.go
index fb6092e0..455f2507 100644
--- a/internal/handshake/header_protector.go
+++ b/internal/handshake/header_protector.go
@@ -17,14 +17,14 @@ type headerProtector interface {
 	DecryptHeader(sample []byte, firstByte *byte, hdrBytes []byte)
 }
 
-func hkdfHeaderProtectionLabel(v protocol.VersionNumber) string {
+func hkdfHeaderProtectionLabel(v protocol.Version) string {
 	if v == protocol.Version2 {
 		return "quicv2 hp"
 	}
 	return "quic hp"
 }
 
-func newHeaderProtector(suite *cipherSuite, trafficSecret []byte, isLongHeader bool, v protocol.VersionNumber) headerProtector {
+func newHeaderProtector(suite *cipherSuite, trafficSecret []byte, isLongHeader bool, v protocol.Version) headerProtector {
 	hkdfLabel := hkdfHeaderProtectionLabel(v)
 	switch suite.ID {
 	case tls.TLS_AES_128_GCM_SHA256, tls.TLS_AES_256_GCM_SHA384:
diff --git a/internal/handshake/initial_aead.go b/internal/handshake/initial_aead.go
index b0377c39..b8aa7e3e 100644
--- a/internal/handshake/initial_aead.go
+++ b/internal/handshake/initial_aead.go
@@ -21,7 +21,7 @@ const (
 	hkdfLabelIVV2  = "quicv2 iv"
 )
 
-func getSalt(v protocol.VersionNumber) []byte {
+func getSalt(v protocol.Version) []byte {
 	if v == protocol.Version2 {
 		return quicSaltV2
 	}
@@ -31,7 +31,7 @@ func getSalt(v protocol.VersionNumber) []byte {
 var initialSuite = getCipherSuite(tls.TLS_AES_128_GCM_SHA256)
 
 // NewInitialAEAD creates a new AEAD for Initial encryption / decryption.
-func NewInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective, v protocol.VersionNumber) (LongHeaderSealer, LongHeaderOpener) {
+func NewInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective, v protocol.Version) (LongHeaderSealer, LongHeaderOpener) {
 	clientSecret, serverSecret := computeSecrets(connID, v)
 	var mySecret, otherSecret []byte
 	if pers == protocol.PerspectiveClient {
@@ -51,14 +51,14 @@ func NewInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective, v p
 		newLongHeaderOpener(decrypter, newAESHeaderProtector(initialSuite, otherSecret, true, hkdfHeaderProtectionLabel(v)))
 }
 
-func computeSecrets(connID protocol.ConnectionID, v protocol.VersionNumber) (clientSecret, serverSecret []byte) {
+func computeSecrets(connID protocol.ConnectionID, v protocol.Version) (clientSecret, serverSecret []byte) {
 	initialSecret := hkdf.Extract(crypto.SHA256.New, connID.Bytes(), getSalt(v))
 	clientSecret = hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "client in", crypto.SHA256.Size())
 	serverSecret = hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "server in", crypto.SHA256.Size())
 	return
 }
 
-func computeInitialKeyAndIV(secret []byte, v protocol.VersionNumber) (key, iv []byte) {
+func computeInitialKeyAndIV(secret []byte, v protocol.Version) (key, iv []byte) {
 	keyLabel := hkdfLabelKeyV1
 	ivLabel := hkdfLabelIVV1
 	if v == protocol.Version2 {
diff --git a/internal/handshake/retry.go b/internal/handshake/retry.go
index 68fa53ed..30643cdf 100644
--- a/internal/handshake/retry.go
+++ b/internal/handshake/retry.go
@@ -40,7 +40,7 @@ var (
 )
 
 // GetRetryIntegrityTag calculates the integrity tag on a Retry packet
-func GetRetryIntegrityTag(retry []byte, origDestConnID protocol.ConnectionID, version protocol.VersionNumber) *[16]byte {
+func GetRetryIntegrityTag(retry []byte, origDestConnID protocol.ConnectionID, version protocol.Version) *[16]byte {
 	retryMutex.Lock()
 	defer retryMutex.Unlock()
 
diff --git a/internal/handshake/updatable_aead.go b/internal/handshake/updatable_aead.go
index f7910ddd..ceaa8047 100644
--- a/internal/handshake/updatable_aead.go
+++ b/internal/handshake/updatable_aead.go
@@ -59,7 +59,7 @@ type updatableAEAD struct {
 
 	tracer  *logging.ConnectionTracer
 	logger  utils.Logger
-	version protocol.VersionNumber
+	version protocol.Version
 
 	// use a single slice to avoid allocations
 	nonceBuf []byte
@@ -70,7 +70,7 @@ var (
 	_ ShortHeaderSealer = &updatableAEAD{}
 )
 
-func newUpdatableAEAD(rttStats *utils.RTTStats, tracer *logging.ConnectionTracer, logger utils.Logger, version protocol.VersionNumber) *updatableAEAD {
+func newUpdatableAEAD(rttStats *utils.RTTStats, tracer *logging.ConnectionTracer, logger utils.Logger, version protocol.Version) *updatableAEAD {
 	return &updatableAEAD{
 		firstPacketNumber:       protocol.InvalidPacketNumber,
 		largestAcked:            protocol.InvalidPacketNumber,
diff --git a/internal/mocks/logging/internal/connection_tracer.go b/internal/mocks/logging/internal/connection_tracer.go
index 1c2c26ae..cc5b8e17 100644
--- a/internal/mocks/logging/internal/connection_tracer.go
+++ b/internal/mocks/logging/internal/connection_tracer.go
@@ -512,7 +512,7 @@ func (c *ConnectionTracerLostPacketCall) DoAndReturn(f func(protocol.EncryptionL
 }
 
 // NegotiatedVersion mocks base method.
-func (m *MockConnectionTracer) NegotiatedVersion(arg0 protocol.VersionNumber, arg1, arg2 []protocol.VersionNumber) {
+func (m *MockConnectionTracer) NegotiatedVersion(arg0 protocol.Version, arg1, arg2 []protocol.Version) {
 	m.ctrl.T.Helper()
 	m.ctrl.Call(m, "NegotiatedVersion", arg0, arg1, arg2)
 }
@@ -536,13 +536,13 @@ func (c *ConnectionTracerNegotiatedVersionCall) Return() *ConnectionTracerNegoti
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *ConnectionTracerNegotiatedVersionCall) Do(f func(protocol.VersionNumber, []protocol.VersionNumber, []protocol.VersionNumber)) *ConnectionTracerNegotiatedVersionCall {
+func (c *ConnectionTracerNegotiatedVersionCall) Do(f func(protocol.Version, []protocol.Version, []protocol.Version)) *ConnectionTracerNegotiatedVersionCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *ConnectionTracerNegotiatedVersionCall) DoAndReturn(f func(protocol.VersionNumber, []protocol.VersionNumber, []protocol.VersionNumber)) *ConnectionTracerNegotiatedVersionCall {
+func (c *ConnectionTracerNegotiatedVersionCall) DoAndReturn(f func(protocol.Version, []protocol.Version, []protocol.Version)) *ConnectionTracerNegotiatedVersionCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
@@ -692,7 +692,7 @@ func (c *ConnectionTracerReceivedTransportParametersCall) DoAndReturn(f func(*wi
 }
 
 // ReceivedVersionNegotiationPacket mocks base method.
-func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0, arg1 protocol.ArbitraryLenConnectionID, arg2 []protocol.VersionNumber) {
+func (m *MockConnectionTracer) ReceivedVersionNegotiationPacket(arg0, arg1 protocol.ArbitraryLenConnectionID, arg2 []protocol.Version) {
 	m.ctrl.T.Helper()
 	m.ctrl.Call(m, "ReceivedVersionNegotiationPacket", arg0, arg1, arg2)
 }
@@ -716,13 +716,13 @@ func (c *ConnectionTracerReceivedVersionNegotiationPacketCall) Return() *Connect
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *ConnectionTracerReceivedVersionNegotiationPacketCall) Do(f func(protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.VersionNumber)) *ConnectionTracerReceivedVersionNegotiationPacketCall {
+func (c *ConnectionTracerReceivedVersionNegotiationPacketCall) Do(f func(protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.Version)) *ConnectionTracerReceivedVersionNegotiationPacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *ConnectionTracerReceivedVersionNegotiationPacketCall) DoAndReturn(f func(protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.VersionNumber)) *ConnectionTracerReceivedVersionNegotiationPacketCall {
+func (c *ConnectionTracerReceivedVersionNegotiationPacketCall) DoAndReturn(f func(protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.Version)) *ConnectionTracerReceivedVersionNegotiationPacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/internal/mocks/logging/internal/tracer.go b/internal/mocks/logging/internal/tracer.go
index 59edf187..e11764c2 100644
--- a/internal/mocks/logging/internal/tracer.go
+++ b/internal/mocks/logging/internal/tracer.go
@@ -114,7 +114,7 @@ func (c *TracerSentPacketCall) DoAndReturn(f func(net.Addr, *wire.Header, protoc
 }
 
 // SentVersionNegotiationPacket mocks base method.
-func (m *MockTracer) SentVersionNegotiationPacket(arg0 net.Addr, arg1, arg2 protocol.ArbitraryLenConnectionID, arg3 []protocol.VersionNumber) {
+func (m *MockTracer) SentVersionNegotiationPacket(arg0 net.Addr, arg1, arg2 protocol.ArbitraryLenConnectionID, arg3 []protocol.Version) {
 	m.ctrl.T.Helper()
 	m.ctrl.Call(m, "SentVersionNegotiationPacket", arg0, arg1, arg2, arg3)
 }
@@ -138,13 +138,13 @@ func (c *TracerSentVersionNegotiationPacketCall) Return() *TracerSentVersionNego
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *TracerSentVersionNegotiationPacketCall) Do(f func(net.Addr, protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.VersionNumber)) *TracerSentVersionNegotiationPacketCall {
+func (c *TracerSentVersionNegotiationPacketCall) Do(f func(net.Addr, protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.Version)) *TracerSentVersionNegotiationPacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *TracerSentVersionNegotiationPacketCall) DoAndReturn(f func(net.Addr, protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.VersionNumber)) *TracerSentVersionNegotiationPacketCall {
+func (c *TracerSentVersionNegotiationPacketCall) DoAndReturn(f func(net.Addr, protocol.ArbitraryLenConnectionID, protocol.ArbitraryLenConnectionID, []protocol.Version)) *TracerSentVersionNegotiationPacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/internal/protocol/version.go b/internal/protocol/version.go
index 5c2decbd..6ee587f3 100644
--- a/internal/protocol/version.go
+++ b/internal/protocol/version.go
@@ -7,8 +7,8 @@ import (
 	"math"
 )
 
-// VersionNumber is a version number as int
-type VersionNumber uint32
+// Version is a version number as int
+type Version uint32
 
 // gQUIC version range as defined in the wiki: https://github.com/quicwg/base-drafts/wiki/QUIC-Versions
 const (
@@ -18,22 +18,22 @@ const (
 
 // The version numbers, making grepping easier
 const (
-	VersionUnknown VersionNumber = math.MaxUint32
-	versionDraft29 VersionNumber = 0xff00001d // draft-29 used to be a widely deployed version
-	Version1       VersionNumber = 0x1
-	Version2       VersionNumber = 0x6b3343cf
+	VersionUnknown Version = math.MaxUint32
+	versionDraft29 Version = 0xff00001d // draft-29 used to be a widely deployed version
+	Version1       Version = 0x1
+	Version2       Version = 0x6b3343cf
 )
 
 // SupportedVersions lists the versions that the server supports
 // must be in sorted descending order
-var SupportedVersions = []VersionNumber{Version1, Version2}
+var SupportedVersions = []Version{Version1, Version2}
 
 // IsValidVersion says if the version is known to quic-go
-func IsValidVersion(v VersionNumber) bool {
+func IsValidVersion(v Version) bool {
 	return v == Version1 || IsSupportedVersion(SupportedVersions, v)
 }
 
-func (vn VersionNumber) String() string {
+func (vn Version) String() string {
 	//nolint:exhaustive
 	switch vn {
 	case VersionUnknown:
@@ -52,16 +52,16 @@ func (vn VersionNumber) String() string {
 	}
 }
 
-func (vn VersionNumber) isGQUIC() bool {
+func (vn Version) isGQUIC() bool {
 	return vn > gquicVersion0 && vn <= maxGquicVersion
 }
 
-func (vn VersionNumber) toGQUICVersion() int {
+func (vn Version) toGQUICVersion() int {
 	return int(10*(vn-gquicVersion0)/0x100) + int(vn%0x10)
 }
 
 // IsSupportedVersion returns true if the server supports this version
-func IsSupportedVersion(supported []VersionNumber, v VersionNumber) bool {
+func IsSupportedVersion(supported []Version, v Version) bool {
 	for _, t := range supported {
 		if t == v {
 			return true
@@ -74,7 +74,7 @@ func IsSupportedVersion(supported []VersionNumber, v VersionNumber) bool {
 // ours is a slice of versions that we support, sorted by our preference (descending)
 // theirs is a slice of versions offered by the peer. The order does not matter.
 // The bool returned indicates if a matching version was found.
-func ChooseSupportedVersion(ours, theirs []VersionNumber) (VersionNumber, bool) {
+func ChooseSupportedVersion(ours, theirs []Version) (Version, bool) {
 	for _, ourVer := range ours {
 		for _, theirVer := range theirs {
 			if ourVer == theirVer {
@@ -86,18 +86,18 @@ func ChooseSupportedVersion(ours, theirs []VersionNumber) (VersionNumber, bool)
 }
 
 // generateReservedVersion generates a reserved version number (v & 0x0f0f0f0f == 0x0a0a0a0a)
-func generateReservedVersion() VersionNumber {
+func generateReservedVersion() Version {
 	b := make([]byte, 4)
 	_, _ = rand.Read(b) // ignore the error here. Failure to read random data doesn't break anything
-	return VersionNumber((binary.BigEndian.Uint32(b) | 0x0a0a0a0a) & 0xfafafafa)
+	return Version((binary.BigEndian.Uint32(b) | 0x0a0a0a0a) & 0xfafafafa)
 }
 
 // GetGreasedVersions adds one reserved version number to a slice of version numbers, at a random position
-func GetGreasedVersions(supported []VersionNumber) []VersionNumber {
+func GetGreasedVersions(supported []Version) []Version {
 	b := make([]byte, 1)
 	_, _ = rand.Read(b) // ignore the error here. Failure to read random data doesn't break anything
 	randPos := int(b[0]) % (len(supported) + 1)
-	greased := make([]VersionNumber, len(supported)+1)
+	greased := make([]Version, len(supported)+1)
 	copy(greased, supported[:randPos])
 	greased[randPos] = generateReservedVersion()
 	copy(greased[randPos+1:], supported[randPos:])
diff --git a/internal/qerr/errors.go b/internal/qerr/errors.go
index 2d8511f7..8f5936df 100644
--- a/internal/qerr/errors.go
+++ b/internal/qerr/errors.go
@@ -101,8 +101,8 @@ func (e *HandshakeTimeoutError) Is(target error) bool { return target == net.Err
 
 // A VersionNegotiationError occurs when the client and the server can't agree on a QUIC version.
 type VersionNegotiationError struct {
-	Ours   []protocol.VersionNumber
-	Theirs []protocol.VersionNumber
+	Ours   []protocol.Version
+	Theirs []protocol.Version
 }
 
 func (e *VersionNegotiationError) Error() string {
diff --git a/internal/wire/ack_frame.go b/internal/wire/ack_frame.go
index 9ce98aee..a0f3feb0 100644
--- a/internal/wire/ack_frame.go
+++ b/internal/wire/ack_frame.go
@@ -22,7 +22,7 @@ type AckFrame struct {
 }
 
 // parseAckFrame reads an ACK frame
-func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.VersionNumber) error {
+func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.Version) error {
 	ecn := typ == ackECNFrameType
 
 	la, err := quicvarint.Read(r)
@@ -110,7 +110,7 @@ func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponen
 }
 
 // Append appends an ACK frame.
-func (f *AckFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *AckFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0
 	if hasECN {
 		b = append(b, ackECNFrameType)
@@ -143,7 +143,7 @@ func (f *AckFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
 }
 
 // Length of a written frame
-func (f *AckFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *AckFrame) Length(_ protocol.Version) protocol.ByteCount {
 	largestAcked := f.AckRanges[0].Largest
 	numRanges := f.numEncodableAckRanges()
 
diff --git a/internal/wire/connection_close_frame.go b/internal/wire/connection_close_frame.go
index f56c2c0d..df362447 100644
--- a/internal/wire/connection_close_frame.go
+++ b/internal/wire/connection_close_frame.go
@@ -16,7 +16,7 @@ type ConnectionCloseFrame struct {
 	ReasonPhrase       string
 }
 
-func parseConnectionCloseFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*ConnectionCloseFrame, error) {
+func parseConnectionCloseFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*ConnectionCloseFrame, error) {
 	f := &ConnectionCloseFrame{IsApplicationError: typ == applicationCloseFrameType}
 	ec, err := quicvarint.Read(r)
 	if err != nil {
@@ -53,7 +53,7 @@ func parseConnectionCloseFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNu
 }
 
 // Length of a written frame
-func (f *ConnectionCloseFrame) Length(protocol.VersionNumber) protocol.ByteCount {
+func (f *ConnectionCloseFrame) Length(protocol.Version) protocol.ByteCount {
 	length := 1 + quicvarint.Len(f.ErrorCode) + quicvarint.Len(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
 	if !f.IsApplicationError {
 		length += quicvarint.Len(f.FrameType) // for the frame type
@@ -61,7 +61,7 @@ func (f *ConnectionCloseFrame) Length(protocol.VersionNumber) protocol.ByteCount
 	return length
 }
 
-func (f *ConnectionCloseFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *ConnectionCloseFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	if f.IsApplicationError {
 		b = append(b, applicationCloseFrameType)
 	} else {
diff --git a/internal/wire/crypto_frame.go b/internal/wire/crypto_frame.go
index 0f005c5b..d4214639 100644
--- a/internal/wire/crypto_frame.go
+++ b/internal/wire/crypto_frame.go
@@ -14,7 +14,7 @@ type CryptoFrame struct {
 	Data   []byte
 }
 
-func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame, error) {
+func parseCryptoFrame(r *bytes.Reader, _ protocol.Version) (*CryptoFrame, error) {
 	frame := &CryptoFrame{}
 	offset, err := quicvarint.Read(r)
 	if err != nil {
@@ -38,7 +38,7 @@ func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame,
 	return frame, nil
 }
 
-func (f *CryptoFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *CryptoFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, cryptoFrameType)
 	b = quicvarint.Append(b, uint64(f.Offset))
 	b = quicvarint.Append(b, uint64(len(f.Data)))
@@ -47,7 +47,7 @@ func (f *CryptoFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error)
 }
 
 // Length of a written frame
-func (f *CryptoFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *CryptoFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.Offset)) + quicvarint.Len(uint64(len(f.Data))) + protocol.ByteCount(len(f.Data))
 }
 
@@ -71,7 +71,7 @@ func (f *CryptoFrame) MaxDataLen(maxSize protocol.ByteCount) protocol.ByteCount
 // The frame might not be split if:
 // * the size is large enough to fit the whole frame
 // * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil.
-func (f *CryptoFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*CryptoFrame, bool /* was splitting required */) {
+func (f *CryptoFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.Version) (*CryptoFrame, bool /* was splitting required */) {
 	if f.Length(version) <= maxSize {
 		return nil, false
 	}
diff --git a/internal/wire/data_blocked_frame.go b/internal/wire/data_blocked_frame.go
index 0d4d1f56..8fe2acb5 100644
--- a/internal/wire/data_blocked_frame.go
+++ b/internal/wire/data_blocked_frame.go
@@ -12,7 +12,7 @@ type DataBlockedFrame struct {
 	MaximumData protocol.ByteCount
 }
 
-func parseDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DataBlockedFrame, error) {
+func parseDataBlockedFrame(r *bytes.Reader, _ protocol.Version) (*DataBlockedFrame, error) {
 	offset, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -20,12 +20,12 @@ func parseDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DataBloc
 	return &DataBlockedFrame{MaximumData: protocol.ByteCount(offset)}, nil
 }
 
-func (f *DataBlockedFrame) Append(b []byte, version protocol.VersionNumber) ([]byte, error) {
+func (f *DataBlockedFrame) Append(b []byte, version protocol.Version) ([]byte, error) {
 	b = append(b, dataBlockedFrameType)
 	return quicvarint.Append(b, uint64(f.MaximumData)), nil
 }
 
 // Length of a written frame
-func (f *DataBlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
+func (f *DataBlockedFrame) Length(version protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.MaximumData))
 }
diff --git a/internal/wire/datagram_frame.go b/internal/wire/datagram_frame.go
index 4d001084..8e406f1a 100644
--- a/internal/wire/datagram_frame.go
+++ b/internal/wire/datagram_frame.go
@@ -20,7 +20,7 @@ type DatagramFrame struct {
 	Data           []byte
 }
 
-func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*DatagramFrame, error) {
+func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*DatagramFrame, error) {
 	f := &DatagramFrame{}
 	f.DataLenPresent = typ&0x1 > 0
 
@@ -45,7 +45,7 @@ func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (
 	return f, nil
 }
 
-func (f *DatagramFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *DatagramFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	typ := uint8(0x30)
 	if f.DataLenPresent {
 		typ ^= 0b1
@@ -59,7 +59,7 @@ func (f *DatagramFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, erro
 }
 
 // MaxDataLen returns the maximum data length
-func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
+func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.Version) protocol.ByteCount {
 	headerLen := protocol.ByteCount(1)
 	if f.DataLenPresent {
 		// pretend that the data size will be 1 bytes
@@ -77,7 +77,7 @@ func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.
 }
 
 // Length of a written frame
-func (f *DatagramFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *DatagramFrame) Length(_ protocol.Version) protocol.ByteCount {
 	length := 1 + protocol.ByteCount(len(f.Data))
 	if f.DataLenPresent {
 		length += quicvarint.Len(uint64(len(f.Data)))
diff --git a/internal/wire/extended_header.go b/internal/wire/extended_header.go
index d10820d6..e04d91b7 100644
--- a/internal/wire/extended_header.go
+++ b/internal/wire/extended_header.go
@@ -32,7 +32,7 @@ type ExtendedHeader struct {
 	parsedLen protocol.ByteCount
 }
 
-func (h *ExtendedHeader) parse(b *bytes.Reader, v protocol.VersionNumber) (bool /* reserved bits valid */, error) {
+func (h *ExtendedHeader) parse(b *bytes.Reader, v protocol.Version) (bool /* reserved bits valid */, error) {
 	startLen := b.Len()
 	// read the (now unencrypted) first byte
 	var err error
@@ -51,7 +51,7 @@ func (h *ExtendedHeader) parse(b *bytes.Reader, v protocol.VersionNumber) (bool
 	return reservedBitsValid, err
 }
 
-func (h *ExtendedHeader) parseLongHeader(b *bytes.Reader, _ protocol.VersionNumber) (bool /* reserved bits valid */, error) {
+func (h *ExtendedHeader) parseLongHeader(b *bytes.Reader, _ protocol.Version) (bool /* reserved bits valid */, error) {
 	if err := h.readPacketNumber(b); err != nil {
 		return false, err
 	}
@@ -95,7 +95,7 @@ func (h *ExtendedHeader) readPacketNumber(b *bytes.Reader) error {
 }
 
 // Append appends the Header.
-func (h *ExtendedHeader) Append(b []byte, v protocol.VersionNumber) ([]byte, error) {
+func (h *ExtendedHeader) Append(b []byte, v protocol.Version) ([]byte, error) {
 	if h.DestConnectionID.Len() > protocol.MaxConnIDLen {
 		return nil, fmt.Errorf("invalid connection ID length: %d bytes", h.DestConnectionID.Len())
 	}
@@ -162,7 +162,7 @@ func (h *ExtendedHeader) ParsedLen() protocol.ByteCount {
 }
 
 // GetLength determines the length of the Header.
-func (h *ExtendedHeader) GetLength(_ protocol.VersionNumber) protocol.ByteCount {
+func (h *ExtendedHeader) GetLength(_ protocol.Version) protocol.ByteCount {
 	length := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn ID len */ + protocol.ByteCount(h.DestConnectionID.Len()) + 1 /* src conn ID len */ + protocol.ByteCount(h.SrcConnectionID.Len()) + protocol.ByteCount(h.PacketNumberLen) + 2 /* length */
 	if h.Type == protocol.PacketTypeInitial {
 		length += quicvarint.Len(uint64(len(h.Token))) + protocol.ByteCount(len(h.Token))
diff --git a/internal/wire/frame_parser.go b/internal/wire/frame_parser.go
index 03d1f131..cf7d4cec 100644
--- a/internal/wire/frame_parser.go
+++ b/internal/wire/frame_parser.go
@@ -59,7 +59,7 @@ func NewFrameParser(supportsDatagrams bool) *FrameParser {
 
 // ParseNext parses the next frame.
 // It skips PADDING frames.
-func (p *FrameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (int, Frame, error) {
+func (p *FrameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel, v protocol.Version) (int, Frame, error) {
 	startLen := len(data)
 	p.r.Reset(data)
 	frame, err := p.parseNext(&p.r, encLevel, v)
@@ -68,7 +68,7 @@ func (p *FrameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel,
 	return n, frame, err
 }
 
-func (p *FrameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (Frame, error) {
+func (p *FrameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) {
 	for r.Len() != 0 {
 		typ, err := quicvarint.Read(r)
 		if err != nil {
@@ -94,7 +94,7 @@ func (p *FrameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLev
 	return nil, nil
 }
 
-func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (Frame, error) {
+func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) {
 	var frame Frame
 	var err error
 	if typ&0xf8 == 0x8 {
diff --git a/internal/wire/handshake_done_frame.go b/internal/wire/handshake_done_frame.go
index 29521bc9..85dd6474 100644
--- a/internal/wire/handshake_done_frame.go
+++ b/internal/wire/handshake_done_frame.go
@@ -7,11 +7,11 @@ import (
 // A HandshakeDoneFrame is a HANDSHAKE_DONE frame
 type HandshakeDoneFrame struct{}
 
-func (f *HandshakeDoneFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *HandshakeDoneFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	return append(b, handshakeDoneFrameType), nil
 }
 
 // Length of a written frame
-func (f *HandshakeDoneFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *HandshakeDoneFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1
 }
diff --git a/internal/wire/header.go b/internal/wire/header.go
index 0c60f4dd..29911684 100644
--- a/internal/wire/header.go
+++ b/internal/wire/header.go
@@ -85,11 +85,11 @@ func IsLongHeaderPacket(firstByte byte) bool {
 
 // ParseVersion parses the QUIC version.
 // It should only be called for Long Header packets (Short Header packets don't contain a version number).
-func ParseVersion(data []byte) (protocol.VersionNumber, error) {
+func ParseVersion(data []byte) (protocol.Version, error) {
 	if len(data) < 5 {
 		return 0, io.EOF
 	}
-	return protocol.VersionNumber(binary.BigEndian.Uint32(data[1:5])), nil
+	return protocol.Version(binary.BigEndian.Uint32(data[1:5])), nil
 }
 
 // IsVersionNegotiationPacket says if this is a version negotiation packet
@@ -109,7 +109,7 @@ func Is0RTTPacket(b []byte) bool {
 	if !IsLongHeaderPacket(b[0]) {
 		return false
 	}
-	version := protocol.VersionNumber(binary.BigEndian.Uint32(b[1:5]))
+	version := protocol.Version(binary.BigEndian.Uint32(b[1:5]))
 	//nolint:exhaustive // We only need to test QUIC versions that we support.
 	switch version {
 	case protocol.Version1:
@@ -128,7 +128,7 @@ type Header struct {
 	typeByte byte
 	Type     protocol.PacketType
 
-	Version          protocol.VersionNumber
+	Version          protocol.Version
 	SrcConnectionID  protocol.ConnectionID
 	DestConnectionID protocol.ConnectionID
 
@@ -184,7 +184,7 @@ func (h *Header) parseLongHeader(b *bytes.Reader) error {
 	if err != nil {
 		return err
 	}
-	h.Version = protocol.VersionNumber(v)
+	h.Version = protocol.Version(v)
 	if h.Version != 0 && h.typeByte&0x40 == 0 {
 		return errors.New("not a QUIC packet")
 	}
@@ -278,7 +278,7 @@ func (h *Header) ParsedLen() protocol.ByteCount {
 
 // ParseExtended parses the version dependent part of the header.
 // The Reader has to be set such that it points to the first byte of the header.
-func (h *Header) ParseExtended(b *bytes.Reader, ver protocol.VersionNumber) (*ExtendedHeader, error) {
+func (h *Header) ParseExtended(b *bytes.Reader, ver protocol.Version) (*ExtendedHeader, error) {
 	extHdr := h.toExtendedHeader()
 	reservedBitsValid, err := extHdr.parse(b, ver)
 	if err != nil {
diff --git a/internal/wire/interface.go b/internal/wire/interface.go
index f19d4647..bc17883b 100644
--- a/internal/wire/interface.go
+++ b/internal/wire/interface.go
@@ -6,6 +6,6 @@ import (
 
 // A Frame in QUIC
 type Frame interface {
-	Append(b []byte, version protocol.VersionNumber) ([]byte, error)
-	Length(version protocol.VersionNumber) protocol.ByteCount
+	Append(b []byte, version protocol.Version) ([]byte, error)
+	Length(version protocol.Version) protocol.ByteCount
 }
diff --git a/internal/wire/max_data_frame.go b/internal/wire/max_data_frame.go
index e61b0f9f..3dfd7611 100644
--- a/internal/wire/max_data_frame.go
+++ b/internal/wire/max_data_frame.go
@@ -13,7 +13,7 @@ type MaxDataFrame struct {
 }
 
 // parseMaxDataFrame parses a MAX_DATA frame
-func parseMaxDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxDataFrame, error) {
+func parseMaxDataFrame(r *bytes.Reader, _ protocol.Version) (*MaxDataFrame, error) {
 	frame := &MaxDataFrame{}
 	byteOffset, err := quicvarint.Read(r)
 	if err != nil {
@@ -23,13 +23,13 @@ func parseMaxDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxDataFrame
 	return frame, nil
 }
 
-func (f *MaxDataFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *MaxDataFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, maxDataFrameType)
 	b = quicvarint.Append(b, uint64(f.MaximumData))
 	return b, nil
 }
 
 // Length of a written frame
-func (f *MaxDataFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *MaxDataFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.MaximumData))
 }
diff --git a/internal/wire/max_stream_data_frame.go b/internal/wire/max_stream_data_frame.go
index fe3d1e3f..cb5eab1b 100644
--- a/internal/wire/max_stream_data_frame.go
+++ b/internal/wire/max_stream_data_frame.go
@@ -13,7 +13,7 @@ type MaxStreamDataFrame struct {
 	MaximumStreamData protocol.ByteCount
 }
 
-func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamDataFrame, error) {
+func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.Version) (*MaxStreamDataFrame, error) {
 	sid, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -29,7 +29,7 @@ func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStr
 	}, nil
 }
 
-func (f *MaxStreamDataFrame) Append(b []byte, version protocol.VersionNumber) ([]byte, error) {
+func (f *MaxStreamDataFrame) Append(b []byte, version protocol.Version) ([]byte, error) {
 	b = append(b, maxStreamDataFrameType)
 	b = quicvarint.Append(b, uint64(f.StreamID))
 	b = quicvarint.Append(b, uint64(f.MaximumStreamData))
@@ -37,6 +37,6 @@ func (f *MaxStreamDataFrame) Append(b []byte, version protocol.VersionNumber) ([
 }
 
 // Length of a written frame
-func (f *MaxStreamDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
+func (f *MaxStreamDataFrame) Length(version protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData))
 }
diff --git a/internal/wire/max_streams_frame.go b/internal/wire/max_streams_frame.go
index bd278c02..d9029338 100644
--- a/internal/wire/max_streams_frame.go
+++ b/internal/wire/max_streams_frame.go
@@ -14,7 +14,7 @@ type MaxStreamsFrame struct {
 	MaxStreamNum protocol.StreamNum
 }
 
-func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*MaxStreamsFrame, error) {
+func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*MaxStreamsFrame, error) {
 	f := &MaxStreamsFrame{}
 	switch typ {
 	case bidiMaxStreamsFrameType:
@@ -33,7 +33,7 @@ func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber)
 	return f, nil
 }
 
-func (f *MaxStreamsFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *MaxStreamsFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	switch f.Type {
 	case protocol.StreamTypeBidi:
 		b = append(b, bidiMaxStreamsFrameType)
@@ -45,6 +45,6 @@ func (f *MaxStreamsFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, er
 }
 
 // Length of a written frame
-func (f *MaxStreamsFrame) Length(protocol.VersionNumber) protocol.ByteCount {
+func (f *MaxStreamsFrame) Length(protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.MaxStreamNum))
 }
diff --git a/internal/wire/new_connection_id_frame.go b/internal/wire/new_connection_id_frame.go
index 713ab996..afae010a 100644
--- a/internal/wire/new_connection_id_frame.go
+++ b/internal/wire/new_connection_id_frame.go
@@ -18,7 +18,7 @@ type NewConnectionIDFrame struct {
 	StatelessResetToken protocol.StatelessResetToken
 }
 
-func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewConnectionIDFrame, error) {
+func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.Version) (*NewConnectionIDFrame, error) {
 	seq, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -57,7 +57,7 @@ func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewC
 	return frame, nil
 }
 
-func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, newConnectionIDFrameType)
 	b = quicvarint.Append(b, f.SequenceNumber)
 	b = quicvarint.Append(b, f.RetirePriorTo)
@@ -72,6 +72,6 @@ func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.VersionNumber) ([]byt
 }
 
 // Length of a written frame
-func (f *NewConnectionIDFrame) Length(protocol.VersionNumber) protocol.ByteCount {
+func (f *NewConnectionIDFrame) Length(protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(f.SequenceNumber) + quicvarint.Len(f.RetirePriorTo) + 1 /* connection ID length */ + protocol.ByteCount(f.ConnectionID.Len()) + 16
 }
diff --git a/internal/wire/new_token_frame.go b/internal/wire/new_token_frame.go
index c3fa178c..6a2eac94 100644
--- a/internal/wire/new_token_frame.go
+++ b/internal/wire/new_token_frame.go
@@ -14,7 +14,7 @@ type NewTokenFrame struct {
 	Token []byte
 }
 
-func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFrame, error) {
+func parseNewTokenFrame(r *bytes.Reader, _ protocol.Version) (*NewTokenFrame, error) {
 	tokenLen, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -32,7 +32,7 @@ func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFra
 	return &NewTokenFrame{Token: token}, nil
 }
 
-func (f *NewTokenFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *NewTokenFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, newTokenFrameType)
 	b = quicvarint.Append(b, uint64(len(f.Token)))
 	b = append(b, f.Token...)
@@ -40,6 +40,6 @@ func (f *NewTokenFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, erro
 }
 
 // Length of a written frame
-func (f *NewTokenFrame) Length(protocol.VersionNumber) protocol.ByteCount {
+func (f *NewTokenFrame) Length(protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(len(f.Token))) + protocol.ByteCount(len(f.Token))
 }
diff --git a/internal/wire/path_challenge_frame.go b/internal/wire/path_challenge_frame.go
index ad024330..772041ac 100644
--- a/internal/wire/path_challenge_frame.go
+++ b/internal/wire/path_challenge_frame.go
@@ -12,7 +12,7 @@ type PathChallengeFrame struct {
 	Data [8]byte
 }
 
-func parsePathChallengeFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathChallengeFrame, error) {
+func parsePathChallengeFrame(r *bytes.Reader, _ protocol.Version) (*PathChallengeFrame, error) {
 	frame := &PathChallengeFrame{}
 	if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
 		if err == io.ErrUnexpectedEOF {
@@ -23,13 +23,13 @@ func parsePathChallengeFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathCh
 	return frame, nil
 }
 
-func (f *PathChallengeFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *PathChallengeFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, pathChallengeFrameType)
 	b = append(b, f.Data[:]...)
 	return b, nil
 }
 
 // Length of a written frame
-func (f *PathChallengeFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *PathChallengeFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + 8
 }
diff --git a/internal/wire/path_response_frame.go b/internal/wire/path_response_frame.go
index 76e65104..86bbe619 100644
--- a/internal/wire/path_response_frame.go
+++ b/internal/wire/path_response_frame.go
@@ -12,7 +12,7 @@ type PathResponseFrame struct {
 	Data [8]byte
 }
 
-func parsePathResponseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathResponseFrame, error) {
+func parsePathResponseFrame(r *bytes.Reader, _ protocol.Version) (*PathResponseFrame, error) {
 	frame := &PathResponseFrame{}
 	if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
 		if err == io.ErrUnexpectedEOF {
@@ -23,13 +23,13 @@ func parsePathResponseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathRes
 	return frame, nil
 }
 
-func (f *PathResponseFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *PathResponseFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, pathResponseFrameType)
 	b = append(b, f.Data[:]...)
 	return b, nil
 }
 
 // Length of a written frame
-func (f *PathResponseFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *PathResponseFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + 8
 }
diff --git a/internal/wire/ping_frame.go b/internal/wire/ping_frame.go
index dd24edc0..71f8d16c 100644
--- a/internal/wire/ping_frame.go
+++ b/internal/wire/ping_frame.go
@@ -7,11 +7,11 @@ import (
 // A PingFrame is a PING frame
 type PingFrame struct{}
 
-func (f *PingFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *PingFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	return append(b, pingFrameType), nil
 }
 
 // Length of a written frame
-func (f *PingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *PingFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1
 }
diff --git a/internal/wire/reset_stream_frame.go b/internal/wire/reset_stream_frame.go
index cd94c940..e60f1db1 100644
--- a/internal/wire/reset_stream_frame.go
+++ b/internal/wire/reset_stream_frame.go
@@ -15,7 +15,7 @@ type ResetStreamFrame struct {
 	FinalSize protocol.ByteCount
 }
 
-func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStreamFrame, error) {
+func parseResetStreamFrame(r *bytes.Reader, _ protocol.Version) (*ResetStreamFrame, error) {
 	var streamID protocol.StreamID
 	var byteOffset protocol.ByteCount
 	sid, err := quicvarint.Read(r)
@@ -40,7 +40,7 @@ func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStr
 	}, nil
 }
 
-func (f *ResetStreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *ResetStreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, resetStreamFrameType)
 	b = quicvarint.Append(b, uint64(f.StreamID))
 	b = quicvarint.Append(b, uint64(f.ErrorCode))
@@ -49,6 +49,6 @@ func (f *ResetStreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, e
 }
 
 // Length of a written frame
-func (f *ResetStreamFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
+func (f *ResetStreamFrame) Length(version protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode)) + quicvarint.Len(uint64(f.FinalSize))
 }
diff --git a/internal/wire/retire_connection_id_frame.go b/internal/wire/retire_connection_id_frame.go
index 8e9a41d8..98153622 100644
--- a/internal/wire/retire_connection_id_frame.go
+++ b/internal/wire/retire_connection_id_frame.go
@@ -12,7 +12,7 @@ type RetireConnectionIDFrame struct {
 	SequenceNumber uint64
 }
 
-func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*RetireConnectionIDFrame, error) {
+func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.Version) (*RetireConnectionIDFrame, error) {
 	seq, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -20,13 +20,13 @@ func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*R
 	return &RetireConnectionIDFrame{SequenceNumber: seq}, nil
 }
 
-func (f *RetireConnectionIDFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *RetireConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, retireConnectionIDFrameType)
 	b = quicvarint.Append(b, f.SequenceNumber)
 	return b, nil
 }
 
 // Length of a written frame
-func (f *RetireConnectionIDFrame) Length(protocol.VersionNumber) protocol.ByteCount {
+func (f *RetireConnectionIDFrame) Length(protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(f.SequenceNumber)
 }
diff --git a/internal/wire/stop_sending_frame.go b/internal/wire/stop_sending_frame.go
index d7b8b240..d314a569 100644
--- a/internal/wire/stop_sending_frame.go
+++ b/internal/wire/stop_sending_frame.go
@@ -15,7 +15,7 @@ type StopSendingFrame struct {
 }
 
 // parseStopSendingFrame parses a STOP_SENDING frame
-func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
+func parseStopSendingFrame(r *bytes.Reader, _ protocol.Version) (*StopSendingFrame, error) {
 	streamID, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -32,11 +32,11 @@ func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSend
 }
 
 // Length of a written frame
-func (f *StopSendingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *StopSendingFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode))
 }
 
-func (f *StopSendingFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *StopSendingFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, stopSendingFrameType)
 	b = quicvarint.Append(b, uint64(f.StreamID))
 	b = quicvarint.Append(b, uint64(f.ErrorCode))
diff --git a/internal/wire/stream_data_blocked_frame.go b/internal/wire/stream_data_blocked_frame.go
index d42e59a2..f79740f9 100644
--- a/internal/wire/stream_data_blocked_frame.go
+++ b/internal/wire/stream_data_blocked_frame.go
@@ -13,7 +13,7 @@ type StreamDataBlockedFrame struct {
 	MaximumStreamData protocol.ByteCount
 }
 
-func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamDataBlockedFrame, error) {
+func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.Version) (*StreamDataBlockedFrame, error) {
 	sid, err := quicvarint.Read(r)
 	if err != nil {
 		return nil, err
@@ -29,7 +29,7 @@ func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*St
 	}, nil
 }
 
-func (f *StreamDataBlockedFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *StreamDataBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	b = append(b, 0x15)
 	b = quicvarint.Append(b, uint64(f.StreamID))
 	b = quicvarint.Append(b, uint64(f.MaximumStreamData))
@@ -37,6 +37,6 @@ func (f *StreamDataBlockedFrame) Append(b []byte, _ protocol.VersionNumber) ([]b
 }
 
 // Length of a written frame
-func (f *StreamDataBlockedFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
+func (f *StreamDataBlockedFrame) Length(version protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData))
 }
diff --git a/internal/wire/stream_frame.go b/internal/wire/stream_frame.go
index d22e1c05..0f6c00da 100644
--- a/internal/wire/stream_frame.go
+++ b/internal/wire/stream_frame.go
@@ -20,7 +20,7 @@ type StreamFrame struct {
 	fromPool bool
 }
 
-func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*StreamFrame, error) {
+func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamFrame, error) {
 	hasOffset := typ&0b100 > 0
 	fin := typ&0b1 > 0
 	hasDataLen := typ&0b10 > 0
@@ -79,7 +79,7 @@ func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*S
 }
 
 // Write writes a STREAM frame
-func (f *StreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *StreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	if len(f.Data) == 0 && !f.Fin {
 		return nil, errors.New("StreamFrame: attempting to write empty frame without FIN")
 	}
@@ -108,7 +108,7 @@ func (f *StreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error)
 }
 
 // Length returns the total length of the STREAM frame
-func (f *StreamFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
+func (f *StreamFrame) Length(version protocol.Version) protocol.ByteCount {
 	length := 1 + quicvarint.Len(uint64(f.StreamID))
 	if f.Offset != 0 {
 		length += quicvarint.Len(uint64(f.Offset))
@@ -126,7 +126,7 @@ func (f *StreamFrame) DataLen() protocol.ByteCount {
 
 // MaxDataLen returns the maximum data length
 // If 0 is returned, writing will fail (a STREAM frame must contain at least 1 byte of data).
-func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
+func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.Version) protocol.ByteCount {
 	headerLen := 1 + quicvarint.Len(uint64(f.StreamID))
 	if f.Offset != 0 {
 		headerLen += quicvarint.Len(uint64(f.Offset))
@@ -151,7 +151,7 @@ func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.Ve
 // The frame might not be split if:
 // * the size is large enough to fit the whole frame
 // * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil.
-func (f *StreamFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.VersionNumber) (*StreamFrame, bool /* was splitting required */) {
+func (f *StreamFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.Version) (*StreamFrame, bool /* was splitting required */) {
 	if maxSize >= f.Length(version) {
 		return nil, false
 	}
diff --git a/internal/wire/streams_blocked_frame.go b/internal/wire/streams_blocked_frame.go
index 4a5951c6..b24619ab 100644
--- a/internal/wire/streams_blocked_frame.go
+++ b/internal/wire/streams_blocked_frame.go
@@ -14,7 +14,7 @@ type StreamsBlockedFrame struct {
 	StreamLimit protocol.StreamNum
 }
 
-func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*StreamsBlockedFrame, error) {
+func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamsBlockedFrame, error) {
 	f := &StreamsBlockedFrame{}
 	switch typ {
 	case bidiStreamBlockedFrameType:
@@ -33,7 +33,7 @@ func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNum
 	return f, nil
 }
 
-func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
+func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
 	switch f.Type {
 	case protocol.StreamTypeBidi:
 		b = append(b, bidiStreamBlockedFrameType)
@@ -45,6 +45,6 @@ func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte
 }
 
 // Length of a written frame
-func (f *StreamsBlockedFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
+func (f *StreamsBlockedFrame) Length(_ protocol.Version) protocol.ByteCount {
 	return 1 + quicvarint.Len(uint64(f.StreamLimit))
 }
diff --git a/internal/wire/version_negotiation.go b/internal/wire/version_negotiation.go
index afde70fa..94d04917 100644
--- a/internal/wire/version_negotiation.go
+++ b/internal/wire/version_negotiation.go
@@ -11,7 +11,7 @@ import (
 )
 
 // ParseVersionNegotiationPacket parses a Version Negotiation packet.
-func ParseVersionNegotiationPacket(b []byte) (dest, src protocol.ArbitraryLenConnectionID, _ []protocol.VersionNumber, _ error) {
+func ParseVersionNegotiationPacket(b []byte) (dest, src protocol.ArbitraryLenConnectionID, _ []protocol.Version, _ error) {
 	n, dest, src, err := ParseArbitraryLenConnectionIDs(b)
 	if err != nil {
 		return nil, nil, nil, err
@@ -25,16 +25,16 @@ func ParseVersionNegotiationPacket(b []byte) (dest, src protocol.ArbitraryLenCon
 		//nolint:stylecheck
 		return nil, nil, nil, errors.New("Version Negotiation packet has a version list with an invalid length")
 	}
-	versions := make([]protocol.VersionNumber, len(b)/4)
+	versions := make([]protocol.Version, len(b)/4)
 	for i := 0; len(b) > 0; i++ {
-		versions[i] = protocol.VersionNumber(binary.BigEndian.Uint32(b[:4]))
+		versions[i] = protocol.Version(binary.BigEndian.Uint32(b[:4]))
 		b = b[4:]
 	}
 	return dest, src, versions, nil
 }
 
 // ComposeVersionNegotiation composes a Version Negotiation
-func ComposeVersionNegotiation(destConnID, srcConnID protocol.ArbitraryLenConnectionID, versions []protocol.VersionNumber) []byte {
+func ComposeVersionNegotiation(destConnID, srcConnID protocol.ArbitraryLenConnectionID, versions []protocol.Version) []byte {
 	greasedVersions := protocol.GetGreasedVersions(versions)
 	expectedLen := 1 /* type byte */ + 4 /* version field */ + 1 /* dest connection ID length field */ + destConnID.Len() + 1 /* src connection ID length field */ + srcConnID.Len() + len(greasedVersions)*4
 	buf := bytes.NewBuffer(make([]byte, 0, expectedLen))
diff --git a/interop/client/main.go b/interop/client/main.go
index 747619a0..a433e443 100644
--- a/interop/client/main.go
+++ b/interop/client/main.go
@@ -107,7 +107,7 @@ func runVersionNegotiationTest(r *http09.RoundTripper, urls []string) error {
 	if len(urls) != 1 {
 		return errors.New("expected at least 2 URLs")
 	}
-	protocol.SupportedVersions = []protocol.VersionNumber{0x1a2a3a4a}
+	protocol.SupportedVersions = []protocol.Version{0x1a2a3a4a}
 	err := downloadFile(r, urls[0], false)
 	if err == nil {
 		return errors.New("expected version negotiation to fail")
diff --git a/logging/interface.go b/logging/interface.go
index 10ac038f..a618a189 100644
--- a/logging/interface.go
+++ b/logging/interface.go
@@ -37,7 +37,7 @@ type (
 	// The StreamType is the type of the stream (unidirectional or bidirectional).
 	StreamType = protocol.StreamType
 	// The VersionNumber is the QUIC version.
-	VersionNumber = protocol.VersionNumber
+	VersionNumber = protocol.Version
 
 	// The Header is the QUIC packet header, before removing header protection.
 	Header = wire.Header
diff --git a/packet_packer.go b/packet_packer.go
index 9a972952..5b055de7 100644
--- a/packet_packer.go
+++ b/packet_packer.go
@@ -18,13 +18,13 @@ import (
 var errNothingToPack = errors.New("nothing to pack")
 
 type packer interface {
-	PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error)
-	PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
-	AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error)
-	MaybePackProbePacket(protocol.EncryptionLevel, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
-	PackConnectionClose(*qerr.TransportError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
-	PackApplicationClose(*qerr.ApplicationError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
-	PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
+	PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error)
+	PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error)
+	AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error)
+	MaybePackProbePacket(protocol.EncryptionLevel, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)
+	PackConnectionClose(*qerr.TransportError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)
+	PackApplicationClose(*qerr.ApplicationError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)
+	PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error)
 
 	SetToken([]byte)
 }
@@ -106,8 +106,8 @@ type sealingManager interface {
 
 type frameSource interface {
 	HasData() bool
-	AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)
-	AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)
+	AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount)
+	AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount)
 }
 
 type ackFrameSource interface {
@@ -170,7 +170,7 @@ func newPacketPacker(
 }
 
 // PackConnectionClose packs a packet that closes the connection with a transport error.
-func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
+func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) {
 	var reason string
 	// don't send details of crypto errors
 	if !e.ErrorCode.IsCryptoError() {
@@ -180,7 +180,7 @@ func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, maxPacketSize
 }
 
 // PackApplicationClose packs a packet that closes the connection with an application error.
-func (p *packetPacker) PackApplicationClose(e *qerr.ApplicationError, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
+func (p *packetPacker) PackApplicationClose(e *qerr.ApplicationError, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) {
 	return p.packConnectionClose(true, uint64(e.ErrorCode), 0, e.ErrorMessage, maxPacketSize, v)
 }
 
@@ -190,7 +190,7 @@ func (p *packetPacker) packConnectionClose(
 	frameType uint64,
 	reason string,
 	maxPacketSize protocol.ByteCount,
-	v protocol.VersionNumber,
+	v protocol.Version,
 ) (*coalescedPacket, error) {
 	var sealers [4]sealer
 	var hdrs [3]*wire.ExtendedHeader
@@ -293,7 +293,7 @@ func (p *packetPacker) packConnectionClose(
 // longHeaderPacketLength calculates the length of a serialized long header packet.
 // It takes into account that packets that have a tiny payload need to be padded,
 // such that len(payload) + packet number len >= 4 + AEAD overhead
-func (p *packetPacker) longHeaderPacketLength(hdr *wire.ExtendedHeader, pl payload, v protocol.VersionNumber) protocol.ByteCount {
+func (p *packetPacker) longHeaderPacketLength(hdr *wire.ExtendedHeader, pl payload, v protocol.Version) protocol.ByteCount {
 	var paddingLen protocol.ByteCount
 	pnLen := protocol.ByteCount(hdr.PacketNumberLen)
 	if pl.length < 4-pnLen {
@@ -328,7 +328,7 @@ func (p *packetPacker) initialPaddingLen(frames []ackhandler.Frame, currentSize,
 // PackCoalescedPacket packs a new packet.
 // It packs an Initial / Handshake if there is data to send in these packet number spaces.
 // It should only be called before the handshake is confirmed.
-func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
+func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) {
 	var (
 		initialHdr, handshakeHdr, zeroRTTHdr                            *wire.ExtendedHeader
 		initialPayload, handshakePayload, zeroRTTPayload, oneRTTPayload payload
@@ -442,7 +442,7 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.
 
 // PackAckOnlyPacket packs a packet containing only an ACK in the application data packet number space.
 // It should be called after the handshake is confirmed.
-func (p *packetPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
+func (p *packetPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
 	buf := getPacketBuffer()
 	packet, err := p.appendPacket(buf, true, maxPacketSize, v)
 	return packet, buf, err
@@ -450,11 +450,11 @@ func (p *packetPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v pro
 
 // AppendPacket packs a packet in the application data packet number space.
 // It should be called after the handshake is confirmed.
-func (p *packetPacker) AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error) {
+func (p *packetPacker) AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) {
 	return p.appendPacket(buf, false, maxPacketSize, v)
 }
 
-func (p *packetPacker) appendPacket(buf *packetBuffer, onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error) {
+func (p *packetPacker) appendPacket(buf *packetBuffer, onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) {
 	sealer, err := p.cryptoSetup.Get1RTTSealer()
 	if err != nil {
 		return shortHeaderPacket{}, err
@@ -471,7 +471,7 @@ func (p *packetPacker) appendPacket(buf *packetBuffer, onlyAck bool, maxPacketSi
 	return p.appendShortHeaderPacket(buf, connID, pn, pnLen, kp, pl, 0, maxPacketSize, sealer, false, v)
 }
 
-func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, encLevel protocol.EncryptionLevel, onlyAck, ackAllowed bool, v protocol.VersionNumber) (*wire.ExtendedHeader, payload) {
+func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, encLevel protocol.EncryptionLevel, onlyAck, ackAllowed bool, v protocol.Version) (*wire.ExtendedHeader, payload) {
 	if onlyAck {
 		if ack := p.acks.GetAckFrame(encLevel, true); ack != nil {
 			return p.getLongHeader(encLevel, v), payload{
@@ -543,7 +543,7 @@ func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, en
 	return hdr, pl
 }
 
-func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*wire.ExtendedHeader, payload) {
+func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxPacketSize protocol.ByteCount, v protocol.Version) (*wire.ExtendedHeader, payload) {
 	if p.perspective != protocol.PerspectiveClient {
 		return nil, payload{}
 	}
@@ -553,12 +553,12 @@ func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxPacketSize
 	return hdr, p.maybeGetAppDataPacket(maxPayloadSize, false, false, v)
 }
 
-func (p *packetPacker) maybeGetShortHeaderPacket(sealer handshake.ShortHeaderSealer, hdrLen protocol.ByteCount, maxPacketSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.VersionNumber) payload {
+func (p *packetPacker) maybeGetShortHeaderPacket(sealer handshake.ShortHeaderSealer, hdrLen protocol.ByteCount, maxPacketSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload {
 	maxPayloadSize := maxPacketSize - hdrLen - protocol.ByteCount(sealer.Overhead())
 	return p.maybeGetAppDataPacket(maxPayloadSize, onlyAck, ackAllowed, v)
 }
 
-func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.VersionNumber) payload {
+func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload {
 	pl := p.composeNextPacket(maxPayloadSize, onlyAck, ackAllowed, v)
 
 	// check if we have anything to send
@@ -581,7 +581,7 @@ func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount,
 	return pl
 }
 
-func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.VersionNumber) payload {
+func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload {
 	if onlyAck {
 		if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, true); ack != nil {
 			return payload{ack: ack, length: ack.Length(v)}
@@ -661,7 +661,7 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAc
 	return pl
 }
 
-func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
+func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) {
 	if encLevel == protocol.Encryption1RTT {
 		s, err := p.cryptoSetup.Get1RTTSealer()
 		if err != nil {
@@ -727,7 +727,7 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, m
 	return packet, nil
 }
 
-func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
+func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
 	pl := payload{
 		frames: []ackhandler.Frame{ping},
 		length: ping.Frame.Length(v),
@@ -745,7 +745,7 @@ func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.B
 	return packet, buffer, err
 }
 
-func (p *packetPacker) getLongHeader(encLevel protocol.EncryptionLevel, v protocol.VersionNumber) *wire.ExtendedHeader {
+func (p *packetPacker) getLongHeader(encLevel protocol.EncryptionLevel, v protocol.Version) *wire.ExtendedHeader {
 	pn, pnLen := p.pnManager.PeekPacketNumber(encLevel)
 	hdr := &wire.ExtendedHeader{
 		PacketNumber:    pn,
@@ -768,7 +768,7 @@ func (p *packetPacker) getLongHeader(encLevel protocol.EncryptionLevel, v protoc
 	return hdr
 }
 
-func (p *packetPacker) appendLongHeaderPacket(buffer *packetBuffer, header *wire.ExtendedHeader, pl payload, padding protocol.ByteCount, encLevel protocol.EncryptionLevel, sealer sealer, v protocol.VersionNumber) (*longHeaderPacket, error) {
+func (p *packetPacker) appendLongHeaderPacket(buffer *packetBuffer, header *wire.ExtendedHeader, pl payload, padding protocol.ByteCount, encLevel protocol.EncryptionLevel, sealer sealer, v protocol.Version) (*longHeaderPacket, error) {
 	var paddingLen protocol.ByteCount
 	pnLen := protocol.ByteCount(header.PacketNumberLen)
 	if pl.length < 4-pnLen {
@@ -814,7 +814,7 @@ func (p *packetPacker) appendShortHeaderPacket(
 	padding, maxPacketSize protocol.ByteCount,
 	sealer sealer,
 	isMTUProbePacket bool,
-	v protocol.VersionNumber,
+	v protocol.Version,
 ) (shortHeaderPacket, error) {
 	var paddingLen protocol.ByteCount
 	if pl.length < 4-protocol.ByteCount(pnLen) {
@@ -860,7 +860,7 @@ func (p *packetPacker) appendShortHeaderPacket(
 
 // appendPacketPayload serializes the payload of a packet into the raw byte slice.
 // It modifies the order of payload.frames.
-func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.VersionNumber) ([]byte, error) {
+func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.Version) ([]byte, error) {
 	payloadOffset := len(raw)
 	if pl.ack != nil {
 		var err error
diff --git a/packet_unpacker.go b/packet_unpacker.go
index 103524c7..1034aab1 100644
--- a/packet_unpacker.go
+++ b/packet_unpacker.go
@@ -53,7 +53,7 @@ func newPacketUnpacker(cs handshake.CryptoSetup, shortHdrConnIDLen int) *packetU
 // If the reserved bits are invalid, the error is wire.ErrInvalidReservedBits.
 // If any other error occurred when parsing the header, the error is of type headerParseError.
 // If decrypting the payload fails for any reason, the error is the error returned by the AEAD.
-func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.VersionNumber) (*unpackedPacket, error) {
+func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.Version) (*unpackedPacket, error) {
 	var encLevel protocol.EncryptionLevel
 	var extHdr *wire.ExtendedHeader
 	var decrypted []byte
@@ -125,7 +125,7 @@ func (u *packetUnpacker) UnpackShortHeader(rcvTime time.Time, data []byte) (prot
 	return pn, pnLen, kp, decrypted, nil
 }
 
-func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte, v protocol.VersionNumber) (*wire.ExtendedHeader, []byte, error) {
+func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, []byte, error) {
 	extHdr, parseErr := u.unpackLongHeader(opener, hdr, data, v)
 	// If the reserved bits are set incorrectly, we still need to continue unpacking.
 	// This avoids a timing side-channel, which otherwise might allow an attacker
@@ -187,7 +187,7 @@ func (u *packetUnpacker) unpackShortHeader(hd headerDecryptor, data []byte) (int
 }
 
 // The error is either nil, a wire.ErrInvalidReservedBits or of type headerParseError.
-func (u *packetUnpacker) unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.VersionNumber) (*wire.ExtendedHeader, error) {
+func (u *packetUnpacker) unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, error) {
 	extHdr, err := unpackLongHeader(hd, hdr, data, v)
 	if err != nil && err != wire.ErrInvalidReservedBits {
 		return nil, &headerParseError{err: err}
@@ -195,7 +195,7 @@ func (u *packetUnpacker) unpackLongHeader(hd headerDecryptor, hdr *wire.Header,
 	return extHdr, err
 }
 
-func unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.VersionNumber) (*wire.ExtendedHeader, error) {
+func unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, error) {
 	r := bytes.NewReader(data)
 
 	hdrLen := hdr.ParsedLen()
diff --git a/qlog/types.go b/qlog/types.go
index e0c0b243..20f10594 100644
--- a/qlog/types.go
+++ b/qlog/types.go
@@ -64,7 +64,7 @@ func (c category) String() string {
 	}
 }
 
-type versionNumber protocol.VersionNumber
+type versionNumber protocol.Version
 
 func (v versionNumber) String() string {
 	return fmt.Sprintf("%x", uint32(v))
diff --git a/retransmission_queue.go b/retransmission_queue.go
index 909ad622..14ae1e3b 100644
--- a/retransmission_queue.go
+++ b/retransmission_queue.go
@@ -74,7 +74,7 @@ func (q *retransmissionQueue) addAppData(f wire.Frame) {
 	q.appData = append(q.appData, f)
 }
 
-func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
+func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
 	if len(q.initialCryptoData) > 0 {
 		f := q.initialCryptoData[0]
 		newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
@@ -97,7 +97,7 @@ func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v proto
 	return f
 }
 
-func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
+func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
 	if len(q.handshakeCryptoData) > 0 {
 		f := q.handshakeCryptoData[0]
 		newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
@@ -120,7 +120,7 @@ func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v pro
 	return f
 }
 
-func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
+func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount, v protocol.Version) wire.Frame {
 	if len(q.appData) == 0 {
 		return nil
 	}
diff --git a/send_stream.go b/send_stream.go
index 070456b8..f4ae5b2a 100644
--- a/send_stream.go
+++ b/send_stream.go
@@ -18,7 +18,7 @@ type sendStreamI interface {
 	SendStream
 	handleStopSendingFrame(*wire.StopSendingFrame)
 	hasData() bool
-	popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (frame ackhandler.StreamFrame, ok, hasMore bool)
+	popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (frame ackhandler.StreamFrame, ok, hasMore bool)
 	closeForShutdown(error)
 	updateSendWindow(protocol.ByteCount)
 }
@@ -198,7 +198,7 @@ func (s *sendStream) canBufferStreamFrame() bool {
 
 // popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream
 // maxBytes is the maximum length this frame (including frame header) will have.
-func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (af ackhandler.StreamFrame, ok, hasMore bool) {
+func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (af ackhandler.StreamFrame, ok, hasMore bool) {
 	s.mutex.Lock()
 	f, hasMoreData := s.popNewOrRetransmittedStreamFrame(maxBytes, v)
 	if f != nil {
@@ -215,7 +215,7 @@ func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Vers
 	}, true, hasMoreData
 }
 
-func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*wire.StreamFrame, bool /* has more data to send */) {
+func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool /* has more data to send */) {
 	if s.cancelWriteErr != nil || s.closeForShutdownErr != nil {
 		return nil, false
 	}
@@ -269,7 +269,7 @@ func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCoun
 	return f, hasMoreData
 }
 
-func (s *sendStream) popNewStreamFrame(maxBytes, sendWindow protocol.ByteCount, v protocol.VersionNumber) (*wire.StreamFrame, bool) {
+func (s *sendStream) popNewStreamFrame(maxBytes, sendWindow protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool) {
 	if s.nextFrame != nil {
 		nextFrame := s.nextFrame
 		s.nextFrame = nil
@@ -304,7 +304,7 @@ func (s *sendStream) popNewStreamFrame(maxBytes, sendWindow protocol.ByteCount,
 	return f, hasMoreData
 }
 
-func (s *sendStream) popNewStreamFrameWithoutBuffer(f *wire.StreamFrame, maxBytes, sendWindow protocol.ByteCount, v protocol.VersionNumber) bool {
+func (s *sendStream) popNewStreamFrameWithoutBuffer(f *wire.StreamFrame, maxBytes, sendWindow protocol.ByteCount, v protocol.Version) bool {
 	maxDataLen := f.MaxDataLen(maxBytes, v)
 	if maxDataLen == 0 { // a STREAM frame must have at least one byte of data
 		return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting
@@ -314,7 +314,7 @@ func (s *sendStream) popNewStreamFrameWithoutBuffer(f *wire.StreamFrame, maxByte
 	return s.dataForWriting != nil || s.nextFrame != nil || s.finishedWriting
 }
 
-func (s *sendStream) maybeGetRetransmission(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*wire.StreamFrame, bool /* has more retransmissions */) {
+func (s *sendStream) maybeGetRetransmission(maxBytes protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool /* has more retransmissions */) {
 	f := s.retransmissionQueue[0]
 	newFrame, needsSplit := f.MaybeSplitOffFrame(maxBytes, v)
 	if needsSplit {
diff --git a/server.go b/server.go
index 930997e7..b96e0b8f 100644
--- a/server.go
+++ b/server.go
@@ -41,7 +41,7 @@ type quicConn interface {
 	EarlyConnection
 	earlyConnReady() <-chan struct{}
 	handlePacket(receivedPacket)
-	GetVersion() protocol.VersionNumber
+	GetVersion() protocol.Version
 	getPerspective() protocol.Perspective
 	run() error
 	destroy(error)
@@ -98,7 +98,7 @@ type baseServer struct {
 		*logging.ConnectionTracer,
 		uint64,
 		utils.Logger,
-		protocol.VersionNumber,
+		protocol.Version,
 	) quicConn
 
 	closeOnce sync.Once
diff --git a/stream.go b/stream.go
index ab76eaf8..ce4374d6 100644
--- a/stream.go
+++ b/stream.go
@@ -60,7 +60,7 @@ type streamI interface {
 	// for sending
 	hasData() bool
 	handleStopSendingFrame(*wire.StopSendingFrame)
-	popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)
+	popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool)
 	updateSendWindow(protocol.ByteCount)
 }
 


Test patch:
diff --git a/client_test.go b/client_test.go
index 4a799746..697abcae 100644
--- a/client_test.go
+++ b/client_test.go
@@ -46,7 +46,7 @@ var _ = Describe("Client", func() {
 			tracer *logging.ConnectionTracer,
 			tracingID uint64,
 			logger utils.Logger,
-			v protocol.VersionNumber,
+			v protocol.Version,
 		) quicConn
 	)
 
@@ -60,7 +60,7 @@ var _ = Describe("Client", func() {
 			Tracer: func(ctx context.Context, perspective logging.Perspective, id ConnectionID) *logging.ConnectionTracer {
 				return tr
 			},
-			Versions: []protocol.VersionNumber{protocol.Version1},
+			Versions: []protocol.Version{protocol.Version1},
 		}
 		Eventually(areConnsRunning).Should(BeFalse())
 		packetConn = NewMockSendConn(mockCtrl)
@@ -125,7 +125,7 @@ var _ = Describe("Client", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				Expect(enable0RTT).To(BeFalse())
 				conn := NewMockQUICConn(mockCtrl)
@@ -162,7 +162,7 @@ var _ = Describe("Client", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				Expect(enable0RTT).To(BeTrue())
 				conn := NewMockQUICConn(mockCtrl)
@@ -199,7 +199,7 @@ var _ = Describe("Client", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				conn := NewMockQUICConn(mockCtrl)
 				conn.EXPECT().run().Return(testErr)
@@ -265,9 +265,9 @@ var _ = Describe("Client", func() {
 		})
 
 		It("creates new connections with the right parameters", func() {
-			config := &Config{Versions: []protocol.VersionNumber{protocol.Version1}}
+			config := &Config{Versions: []protocol.Version{protocol.Version1}}
 			c := make(chan struct{})
-			var version protocol.VersionNumber
+			var version protocol.Version
 			var conf *Config
 			done := make(chan struct{})
 			newClientConnection = func(
@@ -284,7 +284,7 @@ var _ = Describe("Client", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				versionP protocol.VersionNumber,
+				versionP protocol.Version,
 			) quicConn {
 				version = versionP
 				conf = configP
@@ -327,7 +327,7 @@ var _ = Describe("Client", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				versionP protocol.VersionNumber,
+				versionP protocol.Version,
 			) quicConn {
 				conn := NewMockQUICConn(mockCtrl)
 				conn.EXPECT().HandshakeComplete().Return(make(chan struct{}))
@@ -351,7 +351,7 @@ var _ = Describe("Client", func() {
 				return conn
 			}
 
-			config := &Config{Tracer: config.Tracer, Versions: []protocol.VersionNumber{protocol.Version1}}
+			config := &Config{Tracer: config.Tracer, Versions: []protocol.Version{protocol.Version1}}
 			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
 			_, err := DialAddr(context.Background(), "localhost:7890", tlsConf, config)
 			Expect(err).ToNot(HaveOccurred())
diff --git a/config_test.go b/config_test.go
index 500eb1de..8fdf2fae 100644
--- a/config_test.go
+++ b/config_test.go
@@ -68,7 +68,7 @@ var _ = Describe("Config", func() {
 			case "GetConfigForClient", "RequireAddressValidation", "GetLogWriter", "AllowConnectionWindowIncrease", "Tracer":
 				// Can't compare functions.
 			case "Versions":
-				f.Set(reflect.ValueOf([]VersionNumber{1, 2, 3}))
+				f.Set(reflect.ValueOf([]Version{1, 2, 3}))
 			case "ConnectionIDLength":
 				f.Set(reflect.ValueOf(8))
 			case "ConnectionIDGenerator":
diff --git a/connection_test.go b/connection_test.go
index 778a585a..eb8d2625 100644
--- a/connection_test.go
+++ b/connection_test.go
@@ -85,7 +85,7 @@ var _ = Describe("Connection", func() {
 	}
 
 	expectAppendPacket := func(packer *MockPacker, p shortHeaderPacket, b []byte) *PackerAppendPacketCall {
-		return packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), Version1).DoAndReturn(func(buf *packetBuffer, _ protocol.ByteCount, _ protocol.VersionNumber) (shortHeaderPacket, error) {
+		return packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), Version1).DoAndReturn(func(buf *packetBuffer, _ protocol.ByteCount, _ protocol.Version) (shortHeaderPacket, error) {
 			buf.Data = append(buf.Data, b...)
 			return p, nil
 		})
@@ -410,7 +410,7 @@ var _ = Describe("Connection", func() {
 
 	It("tells its versions", func() {
 		conn.version = 4242
-		Expect(conn.GetVersion()).To(Equal(protocol.VersionNumber(4242)))
+		Expect(conn.GetVersion()).To(Equal(protocol.Version(4242)))
 	})
 
 	Context("closing", func() {
@@ -450,7 +450,7 @@ var _ = Describe("Connection", func() {
 			cryptoSetup.EXPECT().Close()
 			buffer := getPacketBuffer()
 			buffer.Data = append(buffer.Data, []byte("connection close")...)
-			packer.EXPECT().PackApplicationClose(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(e *qerr.ApplicationError, _ protocol.ByteCount, _ protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackApplicationClose(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(e *qerr.ApplicationError, _ protocol.ByteCount, _ protocol.Version) (*coalescedPacket, error) {
 				Expect(e.ErrorCode).To(BeEquivalentTo(qerr.NoError))
 				Expect(e.ErrorMessage).To(BeEmpty())
 				return &coalescedPacket{buffer: buffer}, nil
@@ -707,7 +707,7 @@ var _ = Describe("Connection", func() {
 		})
 
 		It("drops packets with an unsupported version", func() {
-			origSupportedVersions := make([]protocol.VersionNumber, len(protocol.SupportedVersions))
+			origSupportedVersions := make([]protocol.Version, len(protocol.SupportedVersions))
 			copy(origSupportedVersions, protocol.SupportedVersions)
 			defer func() {
 				protocol.SupportedVersions = origSupportedVersions
@@ -1065,7 +1065,7 @@ var _ = Describe("Connection", func() {
 
 			It("cuts packets to the right length", func() {
 				hdrLen, packet := getPacketWithLength(srcConnID, 456)
-				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 					Expect(data).To(HaveLen(hdrLen + 456 - 3))
 					return &unpackedPacket{
 						encryptionLevel: protocol.EncryptionHandshake,
@@ -1082,7 +1082,7 @@ var _ = Describe("Connection", func() {
 			It("handles coalesced packets", func() {
 				hdrLen1, packet1 := getPacketWithLength(srcConnID, 456)
 				packet1.ecn = protocol.ECT1
-				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 					Expect(data).To(HaveLen(hdrLen1 + 456 - 3))
 					return &unpackedPacket{
 						encryptionLevel: protocol.EncryptionHandshake,
@@ -1094,7 +1094,7 @@ var _ = Describe("Connection", func() {
 					}, nil
 				})
 				hdrLen2, packet2 := getPacketWithLength(srcConnID, 123)
-				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 					Expect(data).To(HaveLen(hdrLen2 + 123 - 3))
 					return &unpackedPacket{
 						encryptionLevel: protocol.EncryptionHandshake,
@@ -1121,7 +1121,7 @@ var _ = Describe("Connection", func() {
 				hdrLen2, packet2 := getPacketWithLength(srcConnID, 123)
 				gomock.InOrder(
 					unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).Return(nil, handshake.ErrKeysNotYetAvailable),
-					unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+					unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 						Expect(data).To(HaveLen(hdrLen2 + 123 - 3))
 						return &unpackedPacket{
 							encryptionLevel: protocol.EncryptionHandshake,
@@ -1147,7 +1147,7 @@ var _ = Describe("Connection", func() {
 				wrongConnID := protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef})
 				Expect(srcConnID).ToNot(Equal(wrongConnID))
 				hdrLen1, packet1 := getPacketWithLength(srcConnID, 456)
-				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+				unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 					Expect(data).To(HaveLen(hdrLen1 + 456 - 3))
 					return &unpackedPacket{
 						encryptionLevel: protocol.EncryptionHandshake,
@@ -1257,7 +1257,7 @@ var _ = Describe("Connection", func() {
 			sph.EXPECT().SendMode(gomock.Any()).Return(ackhandler.SendAck)
 			sph.EXPECT().ECNMode(gomock.Any()).Return(protocol.ECT1).AnyTimes()
 			done := make(chan struct{})
-			packer.EXPECT().PackCoalescedPacket(true, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackCoalescedPacket(true, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) {
 				close(done)
 				return nil, nil
 			})
@@ -1302,7 +1302,7 @@ var _ = Describe("Connection", func() {
 
 			Context(fmt.Sprintf("sending %s probe packets", encLevel), func() {
 				var sendMode ackhandler.SendMode
-				var getFrame func(protocol.ByteCount, protocol.VersionNumber) wire.Frame
+				var getFrame func(protocol.ByteCount, protocol.Version) wire.Frame
 
 				BeforeEach(func() {
 					//nolint:exhaustive
@@ -2006,7 +2006,7 @@ var _ = Describe("Connection", func() {
 		conn.sentPacketHandler = sph
 		done := make(chan struct{})
 		connRunner.EXPECT().Retire(clientDestConnID)
-		packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *packetBuffer, _ protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error) {
+		packer.EXPECT().AppendPacket(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(_ *packetBuffer, _ protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) {
 			frames, _ := conn.framer.AppendControlFrames(nil, protocol.MaxByteCount, v)
 			Expect(frames).ToNot(BeEmpty())
 			Expect(frames[0].Frame).To(BeEquivalentTo(&wire.HandshakeDoneFrame{}))
@@ -2148,7 +2148,7 @@ var _ = Describe("Connection", func() {
 			setRemoteIdleTimeout(5 * time.Second)
 			conn.lastPacketReceivedTime = time.Now().Add(-5 * time.Second / 2)
 			sent := make(chan struct{})
-			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) {
 				close(sent)
 				return nil, nil
 			})
@@ -2161,7 +2161,7 @@ var _ = Describe("Connection", func() {
 			setRemoteIdleTimeout(time.Hour)
 			conn.lastPacketReceivedTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond)
 			sent := make(chan struct{})
-			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) {
 				close(sent)
 				return nil, nil
 			})
@@ -2194,7 +2194,7 @@ var _ = Describe("Connection", func() {
 			pto := conn.rttStats.PTO(true)
 			conn.lastPacketReceivedTime = time.Now()
 			sentPingTimeChan := make(chan time.Time)
-			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackCoalescedPacket(false, gomock.Any(), conn.version).Do(func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) {
 				sentPingTimeChan <- time.Now()
 				return nil, nil
 			})
@@ -2265,7 +2265,7 @@ var _ = Describe("Connection", func() {
 			conn.config.HandshakeIdleTimeout = 9999 * time.Second
 			conn.config.MaxIdleTimeout = 9999 * time.Second
 			conn.lastPacketReceivedTime = time.Now().Add(-time.Minute)
-			packer.EXPECT().PackApplicationClose(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(e *qerr.ApplicationError, _ protocol.ByteCount, _ protocol.VersionNumber) (*coalescedPacket, error) {
+			packer.EXPECT().PackApplicationClose(gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(e *qerr.ApplicationError, _ protocol.ByteCount, _ protocol.Version) (*coalescedPacket, error) {
 				Expect(e.ErrorCode).To(BeZero())
 				return &coalescedPacket{buffer: getPacketBuffer()}, nil
 			})
@@ -2558,7 +2558,7 @@ var _ = Describe("Client Connection", func() {
 
 	It("changes the connection ID when receiving the first packet from the server", func() {
 		unpacker := NewMockUnpacker(mockCtrl)
-		unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(hdr *wire.Header, _ time.Time, data []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+		unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(hdr *wire.Header, _ time.Time, data []byte, _ protocol.Version) (*unpackedPacket, error) {
 			return &unpackedPacket{
 				encryptionLevel: protocol.Encryption1RTT,
 				hdr:             &wire.ExtendedHeader{Header: *hdr},
@@ -2567,7 +2567,7 @@ var _ = Describe("Client Connection", func() {
 		})
 		conn.unpacker = unpacker
 		done := make(chan struct{})
-		packer.EXPECT().PackCoalescedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
+		packer.EXPECT().PackCoalescedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) {
 			close(done)
 			return nil, nil
 		})
@@ -2614,7 +2614,7 @@ var _ = Describe("Client Connection", func() {
 		})
 		Expect(conn.connIDManager.Get()).To(Equal(protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5})))
 		// now receive a packet with the original source connection ID
-		unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(hdr *wire.Header, _ time.Time, _ []byte, _ protocol.VersionNumber) (*unpackedPacket, error) {
+		unpacker.EXPECT().UnpackLongHeader(gomock.Any(), gomock.Any(), gomock.Any(), conn.version).DoAndReturn(func(hdr *wire.Header, _ time.Time, _ []byte, _ protocol.Version) (*unpackedPacket, error) {
 			return &unpackedPacket{
 				hdr:             &wire.ExtendedHeader{Header: *hdr},
 				data:            []byte{0},
@@ -2694,7 +2694,7 @@ var _ = Describe("Client Connection", func() {
 	})
 
 	Context("handling Version Negotiation", func() {
-		getVNP := func(versions ...protocol.VersionNumber) receivedPacket {
+		getVNP := func(versions ...protocol.Version) receivedPacket {
 			b := wire.ComposeVersionNegotiation(
 				protocol.ArbitraryLenConnectionID(srcConnID.Bytes()),
 				protocol.ArbitraryLenConnectionID(destConnID.Bytes()),
@@ -2712,7 +2712,7 @@ var _ = Describe("Client Connection", func() {
 			conn.sentPacketHandler = sph
 			sph.EXPECT().ReceivedBytes(gomock.Any())
 			sph.EXPECT().PeekPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(128), protocol.PacketNumberLen4)
-			conn.config.Versions = []protocol.VersionNumber{1234, 4321}
+			conn.config.Versions = []protocol.Version{1234, 4321}
 			errChan := make(chan error, 1)
 			start := make(chan struct{})
 			go func() {
@@ -2727,8 +2727,8 @@ var _ = Describe("Client Connection", func() {
 			connRunner.EXPECT().Remove(srcConnID)
 			tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_, _ protocol.ArbitraryLenConnectionID, versions []logging.VersionNumber) {
 				Expect(versions).To(And(
-					ContainElement(protocol.VersionNumber(4321)),
-					ContainElement(protocol.VersionNumber(1337)),
+					ContainElement(protocol.Version(4321)),
+					ContainElement(protocol.Version(1337)),
 				))
 			})
 			cryptoSetup.EXPECT().Close()
@@ -2739,7 +2739,7 @@ var _ = Describe("Client Connection", func() {
 			Expect(err).To(HaveOccurred())
 			Expect(err).To(BeAssignableToTypeOf(&errCloseForRecreating{}))
 			recreateErr := err.(*errCloseForRecreating)
-			Expect(recreateErr.nextVersion).To(Equal(protocol.VersionNumber(4321)))
+			Expect(recreateErr.nextVersion).To(Equal(protocol.Version(4321)))
 			Expect(recreateErr.nextPacketNumber).To(Equal(protocol.PacketNumber(128)))
 		})
 
diff --git a/framer_test.go b/framer_test.go
index 97cbd144..bd376a10 100644
--- a/framer_test.go
+++ b/framer_test.go
@@ -24,7 +24,7 @@ var _ = Describe("Framer", func() {
 		framer           framer
 		stream1, stream2 *MockSendStreamI
 		streamGetter     *MockStreamGetter
-		version          protocol.VersionNumber
+		version          protocol.Version
 	)
 
 	BeforeEach(func() {
@@ -346,7 +346,7 @@ var _ = Describe("Framer", func() {
 		It("pops maximum size STREAM frames", func() {
 			for i := protocol.MinStreamFrameSize; i < 2000; i++ {
 				streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
-				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool) {
+				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
 					f := &wire.StreamFrame{
 						StreamID:       id1,
 						DataLenPresent: true,
@@ -368,7 +368,7 @@ var _ = Describe("Framer", func() {
 			for i := 2 * protocol.MinStreamFrameSize; i < 2000; i++ {
 				streamGetter.EXPECT().GetOrOpenSendStream(id1).Return(stream1, nil)
 				streamGetter.EXPECT().GetOrOpenSendStream(id2).Return(stream2, nil)
-				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool) {
+				stream1.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
 					f := &wire.StreamFrame{
 						StreamID:       id2,
 						DataLenPresent: true,
@@ -376,7 +376,7 @@ var _ = Describe("Framer", func() {
 					f.Data = make([]byte, f.MaxDataLen(protocol.MinStreamFrameSize, v))
 					return ackhandler.StreamFrame{Frame: f}, true, false
 				})
-				stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool) {
+				stream2.EXPECT().popStreamFrame(gomock.Any(), protocol.Version1).DoAndReturn(func(size protocol.ByteCount, v protocol.Version) (ackhandler.StreamFrame, bool, bool) {
 					f := &wire.StreamFrame{
 						StreamID:       id2,
 						DataLenPresent: true,
diff --git a/http3/client_test.go b/http3/client_test.go
index 00d01bca..ed40c4d1 100644
--- a/http3/client_test.go
+++ b/http3/client_test.go
@@ -55,7 +55,7 @@ var _ = Describe("Client", func() {
 
 	It("rejects quic.Configs that allow multiple QUIC versions", func() {
 		qconf := &quic.Config{
-			Versions: []quic.VersionNumber{protocol.Version2, protocol.Version1},
+			Versions: []quic.Version{protocol.Version2, protocol.Version1},
 		}
 		_, err := newClient("localhost:1337", nil, &roundTripperOpts{}, qconf, nil)
 		Expect(err).To(MatchError("can only use a single QUIC version for dialing a HTTP/3 connection"))
@@ -68,7 +68,7 @@ var _ = Describe("Client", func() {
 		dialAddr = func(_ context.Context, _ string, tlsConf *tls.Config, quicConf *quic.Config) (quic.EarlyConnection, error) {
 			Expect(quicConf.MaxIncomingStreams).To(Equal(defaultQuicConfig.MaxIncomingStreams))
 			Expect(tlsConf.NextProtos).To(Equal([]string{NextProtoH3}))
-			Expect(quicConf.Versions).To(Equal([]protocol.VersionNumber{protocol.Version1}))
+			Expect(quicConf.Versions).To(Equal([]protocol.Version{protocol.Version1}))
 			dialAddrCalled = true
 			return nil, errors.New("test done")
 		}
diff --git a/http3/server_test.go b/http3/server_test.go
index ab702c42..1e517ff5 100644
--- a/http3/server_test.go
+++ b/http3/server_test.go
@@ -855,7 +855,7 @@ var _ = Describe("Server", func() {
 
 	Context("setting http headers", func() {
 		BeforeEach(func() {
-			s.QuicConfig = &quic.Config{Versions: []protocol.VersionNumber{protocol.Version1}}
+			s.QuicConfig = &quic.Config{Versions: []protocol.Version{protocol.Version1}}
 		})
 
 		var ln1 QUICEarlyListener
@@ -916,7 +916,7 @@ var _ = Describe("Server", func() {
 		})
 
 		It("works if the quic.Config sets QUIC versions", func() {
-			s.QuicConfig.Versions = []quic.VersionNumber{quic.Version1, quic.Version2}
+			s.QuicConfig.Versions = []quic.Version{quic.Version1, quic.Version2}
 			addListener(":443", &ln1)
 			checkSetHeaders(Equal(http.Header{"Alt-Svc": {`h3=":443"; ma=2592000`}}))
 			removeListener(&ln1)
@@ -955,7 +955,7 @@ var _ = Describe("Server", func() {
 		})
 
 		It("doesn't duplicate Alt-Svc values", func() {
-			s.QuicConfig.Versions = []quic.VersionNumber{quic.Version1, quic.Version1}
+			s.QuicConfig.Versions = []quic.Version{quic.Version1, quic.Version1}
 			addListener(":443", &ln1)
 			checkSetHeaders(Equal(http.Header{"Alt-Svc": {`h3=":443"; ma=2592000`}}))
 			removeListener(&ln1)
@@ -996,7 +996,7 @@ var _ = Describe("Server", func() {
 	Context("ConfigureTLSConfig", func() {
 		It("advertises v1 by default", func() {
 			conf := ConfigureTLSConfig(testdata.GetTLSConfig())
-			ln, err := quic.ListenAddr("localhost:0", conf, &quic.Config{Versions: []quic.VersionNumber{quic.Version1}})
+			ln, err := quic.ListenAddr("localhost:0", conf, &quic.Config{Versions: []quic.Version{quic.Version1}})
 			Expect(err).ToNot(HaveOccurred())
 			defer ln.Close()
 			c, err := quic.DialAddr(context.Background(), ln.Addr().String(), &tls.Config{InsecureSkipVerify: true, NextProtos: []string{NextProtoH3}}, nil)
@@ -1024,7 +1024,7 @@ var _ = Describe("Server", func() {
 				},
 			}
 
-			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.VersionNumber{quic.Version1}})
+			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.Version{quic.Version1}})
 			Expect(err).ToNot(HaveOccurred())
 			defer ln.Close()
 			c, err := quic.DialAddr(context.Background(), ln.Addr().String(), &tls.Config{InsecureSkipVerify: true, NextProtos: []string{NextProtoH3}}, nil)
@@ -1037,7 +1037,7 @@ var _ = Describe("Server", func() {
 			tlsConf := testdata.GetTLSConfig()
 			tlsConf.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { return nil, nil }
 
-			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.VersionNumber{quic.Version1}})
+			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.Version{quic.Version1}})
 			Expect(err).ToNot(HaveOccurred())
 			defer ln.Close()
 			c, err := quic.DialAddr(context.Background(), ln.Addr().String(), &tls.Config{InsecureSkipVerify: true, NextProtos: []string{NextProtoH3}}, nil)
@@ -1055,7 +1055,7 @@ var _ = Describe("Server", func() {
 				},
 			}
 
-			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.VersionNumber{quic.Version1}})
+			ln, err := quic.ListenAddr("localhost:0", ConfigureTLSConfig(tlsConf), &quic.Config{Versions: []quic.Version{quic.Version1}})
 			Expect(err).ToNot(HaveOccurred())
 			defer ln.Close()
 			c, err := quic.DialAddr(context.Background(), ln.Addr().String(), &tls.Config{InsecureSkipVerify: true, NextProtos: []string{NextProtoH3}}, nil)
diff --git a/integrationtests/self/mitm_test.go b/integrationtests/self/mitm_test.go
index 13f4855f..b0b247ba 100644
--- a/integrationtests/self/mitm_test.go
+++ b/integrationtests/self/mitm_test.go
@@ -340,7 +340,7 @@ var _ = Describe("MITM test", func() {
 					}
 
 					// Create fake version negotiation packet with no supported versions
-					versions := []protocol.VersionNumber{}
+					versions := []protocol.Version{}
 					packet := wire.ComposeVersionNegotiation(
 						protocol.ArbitraryLenConnectionID(hdr.SrcConnectionID.Bytes()),
 						protocol.ArbitraryLenConnectionID(hdr.DestConnectionID.Bytes()),
diff --git a/integrationtests/self/self_suite_test.go b/integrationtests/self/self_suite_test.go
index 582575f5..276adf32 100644
--- a/integrationtests/self/self_suite_test.go
+++ b/integrationtests/self/self_suite_test.go
@@ -89,7 +89,7 @@ var (
 	qlogTracer func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer
 	enableQlog bool
 
-	version                          quic.VersionNumber
+	version                          quic.Version
 	tlsConfig                        *tls.Config
 	tlsConfigLongChain               *tls.Config
 	tlsClientConfig                  *tls.Config
@@ -150,7 +150,7 @@ var _ = BeforeSuite(func() {
 		Fail(fmt.Sprintf("unknown QUIC version: %s", versionParam))
 	}
 	fmt.Printf("Using QUIC version: %s\n", version)
-	protocol.SupportedVersions = []quic.VersionNumber{version}
+	protocol.SupportedVersions = []quic.Version{version}
 })
 
 func getTLSConfig() *tls.Config {
diff --git a/integrationtests/versionnegotiation/handshake_test.go b/integrationtests/versionnegotiation/handshake_test.go
index eefcd8e7..6385dacb 100644
--- a/integrationtests/versionnegotiation/handshake_test.go
+++ b/integrationtests/versionnegotiation/handshake_test.go
@@ -18,7 +18,7 @@ import (
 )
 
 type versioner interface {
-	GetVersion() protocol.VersionNumber
+	GetVersion() protocol.Version
 }
 
 type result struct {
@@ -68,11 +68,11 @@ var _ = Describe("Handshake tests", func() {
 		}
 	}
 
-	var supportedVersions []protocol.VersionNumber
+	var supportedVersions []protocol.Version
 
 	BeforeEach(func() {
-		supportedVersions = append([]quic.VersionNumber{}, protocol.SupportedVersions...)
-		protocol.SupportedVersions = append(protocol.SupportedVersions, []protocol.VersionNumber{7, 8, 9, 10}...)
+		supportedVersions = append([]quic.Version{}, protocol.SupportedVersions...)
+		protocol.SupportedVersions = append(protocol.SupportedVersions, []protocol.Version{7, 8, 9, 10}...)
 	})
 
 	AfterEach(func() {
@@ -85,7 +85,7 @@ var _ = Describe("Handshake tests", func() {
 			// the server doesn't support the highest supported version, which is the first one the client will try
 			// but it supports a bunch of versions that the client doesn't speak
 			serverConfig := &quic.Config{}
-			serverConfig.Versions = []protocol.VersionNumber{7, 8, protocol.SupportedVersions[0], 9}
+			serverConfig.Versions = []protocol.Version{7, 8, protocol.SupportedVersions[0], 9}
 			serverResult, serverTracer := newVersionNegotiationTracer()
 			serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
 				return serverTracer
@@ -125,7 +125,7 @@ var _ = Describe("Handshake tests", func() {
 			}
 			server, cl := startServer(getTLSConfig(), serverConfig)
 			defer cl()
-			clientVersions := []protocol.VersionNumber{7, 8, 9, protocol.SupportedVersions[0], 10}
+			clientVersions := []protocol.Version{7, 8, 9, protocol.SupportedVersions[0], 10}
 			clientResult, clientTracer := newVersionNegotiationTracer()
 			conn, err := quic.DialAddr(
 				context.Background(),
@@ -169,7 +169,7 @@ var _ = Describe("Handshake tests", func() {
 			Expect(err).ToNot(HaveOccurred())
 			defer ln.Close()
 
-			clientVersions := []protocol.VersionNumber{7, 8, 9, protocol.SupportedVersions[0], 10}
+			clientVersions := []protocol.Version{7, 8, 9, protocol.SupportedVersions[0], 10}
 			clientResult, clientTracer := newVersionNegotiationTracer()
 			_, err = quic.DialAddr(
 				context.Background(),
diff --git a/internal/handshake/aead_test.go b/internal/handshake/aead_test.go
index 85fe28d8..4527e3e1 100644
--- a/internal/handshake/aead_test.go
+++ b/internal/handshake/aead_test.go
@@ -15,7 +15,7 @@ import (
 )
 
 var _ = Describe("Long Header AEAD", func() {
-	for _, ver := range []protocol.VersionNumber{protocol.Version1, protocol.Version2} {
+	for _, ver := range []protocol.Version{protocol.Version1, protocol.Version2} {
 		v := ver
 
 		Context(fmt.Sprintf("using version %s", v), func() {
diff --git a/internal/handshake/initial_aead_test.go b/internal/handshake/initial_aead_test.go
index 6cd840de..2ce3497f 100644
--- a/internal/handshake/initial_aead_test.go
+++ b/internal/handshake/initial_aead_test.go
@@ -20,7 +20,7 @@ var _ = Describe("Initial AEAD using AES-GCM", func() {
 	connID := protocol.ParseConnectionID(splitHexString("0x8394c8f03e515708"))
 
 	DescribeTable("computes the client key and IV",
-		func(v protocol.VersionNumber, expectedClientSecret, expectedKey, expectedIV []byte) {
+		func(v protocol.Version, expectedClientSecret, expectedKey, expectedIV []byte) {
 			clientSecret, _ := computeSecrets(connID, v)
 			Expect(clientSecret).To(Equal(expectedClientSecret))
 			key, iv := computeInitialKeyAndIV(clientSecret, v)
@@ -42,7 +42,7 @@ var _ = Describe("Initial AEAD using AES-GCM", func() {
 	)
 
 	DescribeTable("computes the server key and IV",
-		func(v protocol.VersionNumber, expectedServerSecret, expectedKey, expectedIV []byte) {
+		func(v protocol.Version, expectedServerSecret, expectedKey, expectedIV []byte) {
 			_, serverSecret := computeSecrets(connID, v)
 			Expect(serverSecret).To(Equal(expectedServerSecret))
 			key, iv := computeInitialKeyAndIV(serverSecret, v)
@@ -64,7 +64,7 @@ var _ = Describe("Initial AEAD using AES-GCM", func() {
 	)
 
 	DescribeTable("encrypts the client's Initial",
-		func(v protocol.VersionNumber, header, data, expectedSample []byte, expectedHdrFirstByte byte, expectedHdr, expectedPacket []byte) {
+		func(v protocol.Version, header, data, expectedSample []byte, expectedHdrFirstByte byte, expectedHdr, expectedPacket []byte) {
 			sealer, _ := NewInitialAEAD(connID, protocol.PerspectiveClient, v)
 			data = append(data, make([]byte, 1162-len(data))...) // add PADDING
 			sealed := sealer.Seal(nil, data, 2, header)
@@ -97,7 +97,7 @@ var _ = Describe("Initial AEAD using AES-GCM", func() {
 	)
 
 	DescribeTable("encrypts the server's Initial",
-		func(v protocol.VersionNumber, header, data, expectedSample, expectedHdr, expectedPacket []byte) {
+		func(v protocol.Version, header, data, expectedSample, expectedHdr, expectedPacket []byte) {
 			sealer, _ := NewInitialAEAD(connID, protocol.PerspectiveServer, v)
 			sealed := sealer.Seal(nil, data, 1, header)
 			sample := sealed[2 : 2+16]
@@ -125,7 +125,7 @@ var _ = Describe("Initial AEAD using AES-GCM", func() {
 		),
 	)
 
-	for _, ver := range []protocol.VersionNumber{protocol.Version1, protocol.Version2} {
+	for _, ver := range []protocol.Version{protocol.Version1, protocol.Version2} {
 		v := ver
 
 		Context(fmt.Sprintf("using version %s", v), func() {
diff --git a/internal/handshake/retry_test.go b/internal/handshake/retry_test.go
index 560e7af5..c30f94e7 100644
--- a/internal/handshake/retry_test.go
+++ b/internal/handshake/retry_test.go
@@ -28,9 +28,9 @@ var _ = Describe("Retry Integrity Check", func() {
 	})
 
 	DescribeTable("using the test vectors",
-		func(version protocol.VersionNumber, data []byte) {
+		func(version protocol.Version, data []byte) {
 			v := binary.BigEndian.Uint32(data[1:5])
-			Expect(protocol.VersionNumber(v)).To(Equal(version))
+			Expect(protocol.Version(v)).To(Equal(version))
 			connID := protocol.ParseConnectionID(splitHexString("0x8394c8f03e515708"))
 			Expect(GetRetryIntegrityTag(data[:len(data)-16], connID, version)[:]).To(Equal(data[len(data)-16:]))
 		},
diff --git a/internal/handshake/updatable_aead_test.go b/internal/handshake/updatable_aead_test.go
index a57030bf..604c08fa 100644
--- a/internal/handshake/updatable_aead_test.go
+++ b/internal/handshake/updatable_aead_test.go
@@ -20,7 +20,7 @@ import (
 
 var _ = Describe("Updatable AEAD", func() {
 	DescribeTable("ChaCha test vector",
-		func(v protocol.VersionNumber, expectedPayload, expectedPacket []byte) {
+		func(v protocol.Version, expectedPayload, expectedPacket []byte) {
 			secret := splitHexString("9ac312a7f877468ebe69422748ad00a1 5443f18203a07d6060f688f30f21632b")
 			aead := newUpdatableAEAD(&utils.RTTStats{}, nil, nil, v)
 			chacha := cipherSuites[2]
@@ -48,7 +48,7 @@ var _ = Describe("Updatable AEAD", func() {
 		),
 	)
 
-	for _, ver := range []protocol.VersionNumber{protocol.Version1, protocol.Version2} {
+	for _, ver := range []protocol.Version{protocol.Version1, protocol.Version2} {
 		v := ver
 
 		Context(fmt.Sprintf("using version %s", v), func() {
diff --git a/internal/protocol/version_test.go b/internal/protocol/version_test.go
index f1bceefc..2f8c0b2d 100644
--- a/internal/protocol/version_test.go
+++ b/internal/protocol/version_test.go
@@ -6,7 +6,7 @@ import (
 )
 
 var _ = Describe("Version", func() {
-	isReservedVersion := func(v VersionNumber) bool {
+	isReservedVersion := func(v Version) bool {
 		return v&0x0f0f0f0f == 0x0a0a0a0a
 	}
 
@@ -24,11 +24,11 @@ var _ = Describe("Version", func() {
 		Expect(Version1.String()).To(Equal("v1"))
 		Expect(Version2.String()).To(Equal("v2"))
 		// check with unsupported version numbers from the wiki
-		Expect(VersionNumber(0x51303039).String()).To(Equal("gQUIC 9"))
-		Expect(VersionNumber(0x51303133).String()).To(Equal("gQUIC 13"))
-		Expect(VersionNumber(0x51303235).String()).To(Equal("gQUIC 25"))
-		Expect(VersionNumber(0x51303438).String()).To(Equal("gQUIC 48"))
-		Expect(VersionNumber(0x01234567).String()).To(Equal("0x1234567"))
+		Expect(Version(0x51303039).String()).To(Equal("gQUIC 9"))
+		Expect(Version(0x51303133).String()).To(Equal("gQUIC 13"))
+		Expect(Version(0x51303235).String()).To(Equal("gQUIC 25"))
+		Expect(Version(0x51303438).String()).To(Equal("gQUIC 48"))
+		Expect(Version(0x01234567).String()).To(Equal("0x1234567"))
 	})
 
 	It("recognizes supported versions", func() {
@@ -39,45 +39,45 @@ var _ = Describe("Version", func() {
 
 	Context("highest supported version", func() {
 		It("finds the supported version", func() {
-			supportedVersions := []VersionNumber{1, 2, 3}
-			other := []VersionNumber{6, 5, 4, 3}
+			supportedVersions := []Version{1, 2, 3}
+			other := []Version{6, 5, 4, 3}
 			ver, ok := ChooseSupportedVersion(supportedVersions, other)
 			Expect(ok).To(BeTrue())
-			Expect(ver).To(Equal(VersionNumber(3)))
+			Expect(ver).To(Equal(Version(3)))
 		})
 
 		It("picks the preferred version", func() {
-			supportedVersions := []VersionNumber{2, 1, 3}
-			other := []VersionNumber{3, 6, 1, 8, 2, 10}
+			supportedVersions := []Version{2, 1, 3}
+			other := []Version{3, 6, 1, 8, 2, 10}
 			ver, ok := ChooseSupportedVersion(supportedVersions, other)
 			Expect(ok).To(BeTrue())
-			Expect(ver).To(Equal(VersionNumber(2)))
+			Expect(ver).To(Equal(Version(2)))
 		})
 
 		It("says when no matching version was found", func() {
-			_, ok := ChooseSupportedVersion([]VersionNumber{1}, []VersionNumber{2})
+			_, ok := ChooseSupportedVersion([]Version{1}, []Version{2})
 			Expect(ok).To(BeFalse())
 		})
 
 		It("handles empty inputs", func() {
-			_, ok := ChooseSupportedVersion([]VersionNumber{102, 101}, []VersionNumber{})
+			_, ok := ChooseSupportedVersion([]Version{102, 101}, []Version{})
 			Expect(ok).To(BeFalse())
-			_, ok = ChooseSupportedVersion([]VersionNumber{}, []VersionNumber{1, 2})
+			_, ok = ChooseSupportedVersion([]Version{}, []Version{1, 2})
 			Expect(ok).To(BeFalse())
-			_, ok = ChooseSupportedVersion([]VersionNumber{}, []VersionNumber{})
+			_, ok = ChooseSupportedVersion([]Version{}, []Version{})
 			Expect(ok).To(BeFalse())
 		})
 	})
 
 	Context("reserved versions", func() {
 		It("adds a greased version if passed an empty slice", func() {
-			greased := GetGreasedVersions([]VersionNumber{})
+			greased := GetGreasedVersions([]Version{})
 			Expect(greased).To(HaveLen(1))
 			Expect(isReservedVersion(greased[0])).To(BeTrue())
 		})
 
 		It("creates greased lists of version numbers", func() {
-			supported := []VersionNumber{10, 18, 29}
+			supported := []Version{10, 18, 29}
 			for _, v := range supported {
 				Expect(isReservedVersion(v)).To(BeFalse())
 			}
diff --git a/internal/qerr/errors_test.go b/internal/qerr/errors_test.go
index 770ebd68..0eeb0408 100644
--- a/internal/qerr/errors_test.go
+++ b/internal/qerr/errors_test.go
@@ -108,8 +108,8 @@ var _ = Describe("QUIC Errors", func() {
 	Context("Version Negotiation errors", func() {
 		It("has a string representation", func() {
 			Expect((&VersionNegotiationError{
-				Ours:   []protocol.VersionNumber{2, 3},
-				Theirs: []protocol.VersionNumber{4, 5, 6},
+				Ours:   []protocol.Version{2, 3},
+				Theirs: []protocol.Version{4, 5, 6},
 			}).Error()).To(Equal("no compatible QUIC version found (we support [0x2 0x3], server offered [0x4 0x5 0x6])"))
 		})
 	})
diff --git a/internal/wire/header_test.go b/internal/wire/header_test.go
index bf083c3f..af8d931e 100644
--- a/internal/wire/header_test.go
+++ b/internal/wire/header_test.go
@@ -95,7 +95,7 @@ var _ = Describe("Header Parsing", func() {
 			b := []byte{0x80, 0xde, 0xad, 0xbe, 0xef}
 			v, err := ParseVersion(b)
 			Expect(err).ToNot(HaveOccurred())
-			Expect(v).To(Equal(protocol.VersionNumber(0xdeadbeef)))
+			Expect(v).To(Equal(protocol.Version(0xdeadbeef)))
 		})
 
 		It("errors with EOF", func() {
@@ -230,7 +230,7 @@ var _ = Describe("Header Parsing", func() {
 			}
 			hdr, _, rest, err := ParsePacket(data)
 			Expect(err).To(MatchError(ErrUnsupportedVersion))
-			Expect(hdr.Version).To(Equal(protocol.VersionNumber(0xdeadbeef)))
+			Expect(hdr.Version).To(Equal(protocol.Version(0xdeadbeef)))
 			Expect(hdr.DestConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8})))
 			Expect(hdr.SrcConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1})))
 			Expect(rest).To(BeEmpty())
diff --git a/internal/wire/version_negotiation_test.go b/internal/wire/version_negotiation_test.go
index acd6d7ce..d39d94a0 100644
--- a/internal/wire/version_negotiation_test.go
+++ b/internal/wire/version_negotiation_test.go
@@ -22,7 +22,7 @@ var _ = Describe("Version Negotiation Packets", func() {
 	It("parses a Version Negotiation packet", func() {
 		srcConnID := randConnID(rand.Intn(255) + 1)
 		destConnID := randConnID(rand.Intn(255) + 1)
-		versions := []protocol.VersionNumber{0x22334455, 0x33445566}
+		versions := []protocol.Version{0x22334455, 0x33445566}
 		data := []byte{0x80, 0, 0, 0, 0}
 		data = append(data, uint8(len(destConnID)))
 		data = append(data, destConnID...)
@@ -42,7 +42,7 @@ var _ = Describe("Version Negotiation Packets", func() {
 
 	It("errors if it contains versions of the wrong length", func() {
 		connID := protocol.ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
-		versions := []protocol.VersionNumber{0x22334455, 0x33445566}
+		versions := []protocol.Version{0x22334455, 0x33445566}
 		data := ComposeVersionNegotiation(connID, connID, versions)
 		_, _, _, err := ParseVersionNegotiationPacket(data[:len(data)-2])
 		Expect(err).To(MatchError("Version Negotiation packet has a version list with an invalid length"))
@@ -50,7 +50,7 @@ var _ = Describe("Version Negotiation Packets", func() {
 
 	It("errors if the version list is empty", func() {
 		connID := protocol.ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
-		versions := []protocol.VersionNumber{0x22334455}
+		versions := []protocol.Version{0x22334455}
 		data := ComposeVersionNegotiation(connID, connID, versions)
 		// remove 8 bytes (two versions), since ComposeVersionNegotiation also added a reserved version number
 		data = data[:len(data)-8]
@@ -61,7 +61,7 @@ var _ = Describe("Version Negotiation Packets", func() {
 	It("adds a reserved version", func() {
 		srcConnID := protocol.ArbitraryLenConnectionID{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}
 		destConnID := protocol.ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
-		versions := []protocol.VersionNumber{1001, 1003}
+		versions := []protocol.Version{1001, 1003}
 		data := ComposeVersionNegotiation(destConnID, srcConnID, versions)
 		Expect(IsLongHeaderPacket(data[0])).To(BeTrue())
 		Expect(data[0] & 0x40).ToNot(BeZero())
@@ -77,7 +77,7 @@ var _ = Describe("Version Negotiation Packets", func() {
 		for _, v := range versions {
 			Expect(supportedVersions).To(ContainElement(v))
 		}
-		var reservedVersion protocol.VersionNumber
+		var reservedVersion protocol.Version
 	versionLoop:
 		for _, ver := range supportedVersions {
 			for _, v := range versions {
diff --git a/internal/wire/wire_suite_test.go b/internal/wire/wire_suite_test.go
index d68c6ee7..33d3601b 100644
--- a/internal/wire/wire_suite_test.go
+++ b/internal/wire/wire_suite_test.go
@@ -20,7 +20,7 @@ func encodeVarInt(i uint64) []byte {
 	return quicvarint.Append(nil, i)
 }
 
-func appendVersion(data []byte, v protocol.VersionNumber) []byte {
+func appendVersion(data []byte, v protocol.Version) []byte {
 	offset := len(data)
 	data = append(data, []byte{0, 0, 0, 0}...)
 	binary.BigEndian.PutUint32(data[offset:], uint32(v))
diff --git a/logging/multiplex_test.go b/logging/multiplex_test.go
index e27ddc8c..94604096 100644
--- a/logging/multiplex_test.go
+++ b/logging/multiplex_test.go
@@ -93,8 +93,8 @@ var _ = Describe("Tracing", func() {
 
 		It("traces the NegotiatedVersion event", func() {
 			chosen := protocol.Version2
-			client := []protocol.VersionNumber{protocol.Version1}
-			server := []protocol.VersionNumber{13, 37}
+			client := []protocol.Version{protocol.Version1}
+			server := []protocol.Version{13, 37}
 			tr1.EXPECT().NegotiatedVersion(chosen, client, server)
 			tr2.EXPECT().NegotiatedVersion(chosen, client, server)
 			tracer.NegotiatedVersion(chosen, client, server)
diff --git a/mock_frame_source_test.go b/mock_frame_source_test.go
index df86b7be..cc6acc6a 100644
--- a/mock_frame_source_test.go
+++ b/mock_frame_source_test.go
@@ -40,7 +40,7 @@ func (m *MockFrameSource) EXPECT() *MockFrameSourceMockRecorder {
 }
 
 // AppendControlFrames mocks base method.
-func (m *MockFrameSource) AppendControlFrames(arg0 []ackhandler.Frame, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
+func (m *MockFrameSource) AppendControlFrames(arg0 []ackhandler.Frame, arg1 protocol.ByteCount, arg2 protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "AppendControlFrames", arg0, arg1, arg2)
 	ret0, _ := ret[0].([]ackhandler.Frame)
@@ -67,19 +67,19 @@ func (c *FrameSourceAppendControlFramesCall) Return(arg0 []ackhandler.Frame, arg
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *FrameSourceAppendControlFramesCall) Do(f func([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)) *FrameSourceAppendControlFramesCall {
+func (c *FrameSourceAppendControlFramesCall) Do(f func([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount)) *FrameSourceAppendControlFramesCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *FrameSourceAppendControlFramesCall) DoAndReturn(f func([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)) *FrameSourceAppendControlFramesCall {
+func (c *FrameSourceAppendControlFramesCall) DoAndReturn(f func([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount)) *FrameSourceAppendControlFramesCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // AppendStreamFrames mocks base method.
-func (m *MockFrameSource) AppendStreamFrames(arg0 []ackhandler.StreamFrame, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+func (m *MockFrameSource) AppendStreamFrames(arg0 []ackhandler.StreamFrame, arg1 protocol.ByteCount, arg2 protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "AppendStreamFrames", arg0, arg1, arg2)
 	ret0, _ := ret[0].([]ackhandler.StreamFrame)
@@ -106,13 +106,13 @@ func (c *FrameSourceAppendStreamFramesCall) Return(arg0 []ackhandler.StreamFrame
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *FrameSourceAppendStreamFramesCall) Do(f func([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)) *FrameSourceAppendStreamFramesCall {
+func (c *FrameSourceAppendStreamFramesCall) Do(f func([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount)) *FrameSourceAppendStreamFramesCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *FrameSourceAppendStreamFramesCall) DoAndReturn(f func([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)) *FrameSourceAppendStreamFramesCall {
+func (c *FrameSourceAppendStreamFramesCall) DoAndReturn(f func([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount)) *FrameSourceAppendStreamFramesCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/mock_packer_test.go b/mock_packer_test.go
index 8ef1c323..4e846b37 100644
--- a/mock_packer_test.go
+++ b/mock_packer_test.go
@@ -41,7 +41,7 @@ func (m *MockPacker) EXPECT() *MockPackerMockRecorder {
 }
 
 // AppendPacket mocks base method.
-func (m *MockPacker) AppendPacket(arg0 *packetBuffer, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (shortHeaderPacket, error) {
+func (m *MockPacker) AppendPacket(arg0 *packetBuffer, arg1 protocol.ByteCount, arg2 protocol.Version) (shortHeaderPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "AppendPacket", arg0, arg1, arg2)
 	ret0, _ := ret[0].(shortHeaderPacket)
@@ -68,19 +68,19 @@ func (c *PackerAppendPacketCall) Return(arg0 shortHeaderPacket, arg1 error) *Pac
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerAppendPacketCall) Do(f func(*packetBuffer, protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, error)) *PackerAppendPacketCall {
+func (c *PackerAppendPacketCall) Do(f func(*packetBuffer, protocol.ByteCount, protocol.Version) (shortHeaderPacket, error)) *PackerAppendPacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerAppendPacketCall) DoAndReturn(f func(*packetBuffer, protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, error)) *PackerAppendPacketCall {
+func (c *PackerAppendPacketCall) DoAndReturn(f func(*packetBuffer, protocol.ByteCount, protocol.Version) (shortHeaderPacket, error)) *PackerAppendPacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // MaybePackProbePacket mocks base method.
-func (m *MockPacker) MaybePackProbePacket(arg0 protocol.EncryptionLevel, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (*coalescedPacket, error) {
+func (m *MockPacker) MaybePackProbePacket(arg0 protocol.EncryptionLevel, arg1 protocol.ByteCount, arg2 protocol.Version) (*coalescedPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "MaybePackProbePacket", arg0, arg1, arg2)
 	ret0, _ := ret[0].(*coalescedPacket)
@@ -107,19 +107,19 @@ func (c *PackerMaybePackProbePacketCall) Return(arg0 *coalescedPacket, arg1 erro
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerMaybePackProbePacketCall) Do(f func(protocol.EncryptionLevel, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerMaybePackProbePacketCall {
+func (c *PackerMaybePackProbePacketCall) Do(f func(protocol.EncryptionLevel, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerMaybePackProbePacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerMaybePackProbePacketCall) DoAndReturn(f func(protocol.EncryptionLevel, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerMaybePackProbePacketCall {
+func (c *PackerMaybePackProbePacketCall) DoAndReturn(f func(protocol.EncryptionLevel, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerMaybePackProbePacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // PackAckOnlyPacket mocks base method.
-func (m *MockPacker) PackAckOnlyPacket(arg0 protocol.ByteCount, arg1 protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
+func (m *MockPacker) PackAckOnlyPacket(arg0 protocol.ByteCount, arg1 protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "PackAckOnlyPacket", arg0, arg1)
 	ret0, _ := ret[0].(shortHeaderPacket)
@@ -147,19 +147,19 @@ func (c *PackerPackAckOnlyPacketCall) Return(arg0 shortHeaderPacket, arg1 *packe
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerPackAckOnlyPacketCall) Do(f func(protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)) *PackerPackAckOnlyPacketCall {
+func (c *PackerPackAckOnlyPacketCall) Do(f func(protocol.ByteCount, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *PackerPackAckOnlyPacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerPackAckOnlyPacketCall) DoAndReturn(f func(protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)) *PackerPackAckOnlyPacketCall {
+func (c *PackerPackAckOnlyPacketCall) DoAndReturn(f func(protocol.ByteCount, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *PackerPackAckOnlyPacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // PackApplicationClose mocks base method.
-func (m *MockPacker) PackApplicationClose(arg0 *qerr.ApplicationError, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (*coalescedPacket, error) {
+func (m *MockPacker) PackApplicationClose(arg0 *qerr.ApplicationError, arg1 protocol.ByteCount, arg2 protocol.Version) (*coalescedPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "PackApplicationClose", arg0, arg1, arg2)
 	ret0, _ := ret[0].(*coalescedPacket)
@@ -186,19 +186,19 @@ func (c *PackerPackApplicationCloseCall) Return(arg0 *coalescedPacket, arg1 erro
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerPackApplicationCloseCall) Do(f func(*qerr.ApplicationError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackApplicationCloseCall {
+func (c *PackerPackApplicationCloseCall) Do(f func(*qerr.ApplicationError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackApplicationCloseCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerPackApplicationCloseCall) DoAndReturn(f func(*qerr.ApplicationError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackApplicationCloseCall {
+func (c *PackerPackApplicationCloseCall) DoAndReturn(f func(*qerr.ApplicationError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackApplicationCloseCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // PackCoalescedPacket mocks base method.
-func (m *MockPacker) PackCoalescedPacket(arg0 bool, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (*coalescedPacket, error) {
+func (m *MockPacker) PackCoalescedPacket(arg0 bool, arg1 protocol.ByteCount, arg2 protocol.Version) (*coalescedPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "PackCoalescedPacket", arg0, arg1, arg2)
 	ret0, _ := ret[0].(*coalescedPacket)
@@ -225,19 +225,19 @@ func (c *PackerPackCoalescedPacketCall) Return(arg0 *coalescedPacket, arg1 error
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerPackCoalescedPacketCall) Do(f func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackCoalescedPacketCall {
+func (c *PackerPackCoalescedPacketCall) Do(f func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackCoalescedPacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerPackCoalescedPacketCall) DoAndReturn(f func(bool, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackCoalescedPacketCall {
+func (c *PackerPackCoalescedPacketCall) DoAndReturn(f func(bool, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackCoalescedPacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // PackConnectionClose mocks base method.
-func (m *MockPacker) PackConnectionClose(arg0 *qerr.TransportError, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (*coalescedPacket, error) {
+func (m *MockPacker) PackConnectionClose(arg0 *qerr.TransportError, arg1 protocol.ByteCount, arg2 protocol.Version) (*coalescedPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "PackConnectionClose", arg0, arg1, arg2)
 	ret0, _ := ret[0].(*coalescedPacket)
@@ -264,19 +264,19 @@ func (c *PackerPackConnectionCloseCall) Return(arg0 *coalescedPacket, arg1 error
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerPackConnectionCloseCall) Do(f func(*qerr.TransportError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackConnectionCloseCall {
+func (c *PackerPackConnectionCloseCall) Do(f func(*qerr.TransportError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackConnectionCloseCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerPackConnectionCloseCall) DoAndReturn(f func(*qerr.TransportError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)) *PackerPackConnectionCloseCall {
+func (c *PackerPackConnectionCloseCall) DoAndReturn(f func(*qerr.TransportError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error)) *PackerPackConnectionCloseCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
 
 // PackMTUProbePacket mocks base method.
-func (m *MockPacker) PackMTUProbePacket(arg0 ackhandler.Frame, arg1 protocol.ByteCount, arg2 protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
+func (m *MockPacker) PackMTUProbePacket(arg0 ackhandler.Frame, arg1 protocol.ByteCount, arg2 protocol.Version) (shortHeaderPacket, *packetBuffer, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "PackMTUProbePacket", arg0, arg1, arg2)
 	ret0, _ := ret[0].(shortHeaderPacket)
@@ -304,13 +304,13 @@ func (c *PackerPackMTUProbePacketCall) Return(arg0 shortHeaderPacket, arg1 *pack
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *PackerPackMTUProbePacketCall) Do(f func(ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)) *PackerPackMTUProbePacketCall {
+func (c *PackerPackMTUProbePacketCall) Do(f func(ackhandler.Frame, protocol.ByteCount, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *PackerPackMTUProbePacketCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *PackerPackMTUProbePacketCall) DoAndReturn(f func(ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)) *PackerPackMTUProbePacketCall {
+func (c *PackerPackMTUProbePacketCall) DoAndReturn(f func(ackhandler.Frame, protocol.ByteCount, protocol.Version) (shortHeaderPacket, *packetBuffer, error)) *PackerPackMTUProbePacketCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/mock_quic_conn_test.go b/mock_quic_conn_test.go
index ce0d6192..332f8e75 100644
--- a/mock_quic_conn_test.go
+++ b/mock_quic_conn_test.go
@@ -234,10 +234,10 @@ func (c *QUICConnContextCall) DoAndReturn(f func() context.Context) *QUICConnCon
 }
 
 // GetVersion mocks base method.
-func (m *MockQUICConn) GetVersion() protocol.VersionNumber {
+func (m *MockQUICConn) GetVersion() protocol.Version {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetVersion")
-	ret0, _ := ret[0].(protocol.VersionNumber)
+	ret0, _ := ret[0].(protocol.Version)
 	return ret0
 }
 
@@ -254,19 +254,19 @@ type QUICConnGetVersionCall struct {
 }
 
 // Return rewrite *gomock.Call.Return
-func (c *QUICConnGetVersionCall) Return(arg0 protocol.VersionNumber) *QUICConnGetVersionCall {
+func (c *QUICConnGetVersionCall) Return(arg0 protocol.Version) *QUICConnGetVersionCall {
 	c.Call = c.Call.Return(arg0)
 	return c
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *QUICConnGetVersionCall) Do(f func() protocol.VersionNumber) *QUICConnGetVersionCall {
+func (c *QUICConnGetVersionCall) Do(f func() protocol.Version) *QUICConnGetVersionCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *QUICConnGetVersionCall) DoAndReturn(f func() protocol.VersionNumber) *QUICConnGetVersionCall {
+func (c *QUICConnGetVersionCall) DoAndReturn(f func() protocol.Version) *QUICConnGetVersionCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/mock_send_stream_internal_test.go b/mock_send_stream_internal_test.go
index 53093155..a8013965 100644
--- a/mock_send_stream_internal_test.go
+++ b/mock_send_stream_internal_test.go
@@ -381,7 +381,7 @@ func (c *SendStreamIhasDataCall) DoAndReturn(f func() bool) *SendStreamIhasDataC
 }
 
 // popStreamFrame mocks base method.
-func (m *MockSendStreamI) popStreamFrame(arg0 protocol.ByteCount, arg1 protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool) {
+func (m *MockSendStreamI) popStreamFrame(arg0 protocol.ByteCount, arg1 protocol.Version) (ackhandler.StreamFrame, bool, bool) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "popStreamFrame", arg0, arg1)
 	ret0, _ := ret[0].(ackhandler.StreamFrame)
@@ -409,13 +409,13 @@ func (c *SendStreamIpopStreamFrameCall) Return(arg0 ackhandler.StreamFrame, arg1
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *SendStreamIpopStreamFrameCall) Do(f func(protocol.ByteCount, protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)) *SendStreamIpopStreamFrameCall {
+func (c *SendStreamIpopStreamFrameCall) Do(f func(protocol.ByteCount, protocol.Version) (ackhandler.StreamFrame, bool, bool)) *SendStreamIpopStreamFrameCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *SendStreamIpopStreamFrameCall) DoAndReturn(f func(protocol.ByteCount, protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)) *SendStreamIpopStreamFrameCall {
+func (c *SendStreamIpopStreamFrameCall) DoAndReturn(f func(protocol.ByteCount, protocol.Version) (ackhandler.StreamFrame, bool, bool)) *SendStreamIpopStreamFrameCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/mock_stream_internal_test.go b/mock_stream_internal_test.go
index 21ba4f06..886528a8 100644
--- a/mock_stream_internal_test.go
+++ b/mock_stream_internal_test.go
@@ -646,7 +646,7 @@ func (c *StreamIhasDataCall) DoAndReturn(f func() bool) *StreamIhasDataCall {
 }
 
 // popStreamFrame mocks base method.
-func (m *MockStreamI) popStreamFrame(arg0 protocol.ByteCount, arg1 protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool) {
+func (m *MockStreamI) popStreamFrame(arg0 protocol.ByteCount, arg1 protocol.Version) (ackhandler.StreamFrame, bool, bool) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "popStreamFrame", arg0, arg1)
 	ret0, _ := ret[0].(ackhandler.StreamFrame)
@@ -674,13 +674,13 @@ func (c *StreamIpopStreamFrameCall) Return(arg0 ackhandler.StreamFrame, arg1, ar
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *StreamIpopStreamFrameCall) Do(f func(protocol.ByteCount, protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)) *StreamIpopStreamFrameCall {
+func (c *StreamIpopStreamFrameCall) Do(f func(protocol.ByteCount, protocol.Version) (ackhandler.StreamFrame, bool, bool)) *StreamIpopStreamFrameCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *StreamIpopStreamFrameCall) DoAndReturn(f func(protocol.ByteCount, protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)) *StreamIpopStreamFrameCall {
+func (c *StreamIpopStreamFrameCall) DoAndReturn(f func(protocol.ByteCount, protocol.Version) (ackhandler.StreamFrame, bool, bool)) *StreamIpopStreamFrameCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/mock_unpacker_test.go b/mock_unpacker_test.go
index 006d9fec..43d2ce69 100644
--- a/mock_unpacker_test.go
+++ b/mock_unpacker_test.go
@@ -41,7 +41,7 @@ func (m *MockUnpacker) EXPECT() *MockUnpackerMockRecorder {
 }
 
 // UnpackLongHeader mocks base method.
-func (m *MockUnpacker) UnpackLongHeader(arg0 *wire.Header, arg1 time.Time, arg2 []byte, arg3 protocol.VersionNumber) (*unpackedPacket, error) {
+func (m *MockUnpacker) UnpackLongHeader(arg0 *wire.Header, arg1 time.Time, arg2 []byte, arg3 protocol.Version) (*unpackedPacket, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UnpackLongHeader", arg0, arg1, arg2, arg3)
 	ret0, _ := ret[0].(*unpackedPacket)
@@ -68,13 +68,13 @@ func (c *UnpackerUnpackLongHeaderCall) Return(arg0 *unpackedPacket, arg1 error)
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *UnpackerUnpackLongHeaderCall) Do(f func(*wire.Header, time.Time, []byte, protocol.VersionNumber) (*unpackedPacket, error)) *UnpackerUnpackLongHeaderCall {
+func (c *UnpackerUnpackLongHeaderCall) Do(f func(*wire.Header, time.Time, []byte, protocol.Version) (*unpackedPacket, error)) *UnpackerUnpackLongHeaderCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *UnpackerUnpackLongHeaderCall) DoAndReturn(f func(*wire.Header, time.Time, []byte, protocol.VersionNumber) (*unpackedPacket, error)) *UnpackerUnpackLongHeaderCall {
+func (c *UnpackerUnpackLongHeaderCall) DoAndReturn(f func(*wire.Header, time.Time, []byte, protocol.Version) (*unpackedPacket, error)) *UnpackerUnpackLongHeaderCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/packet_packer_test.go b/packet_packer_test.go
index 5b227b73..27dfb748 100644
--- a/packet_packer_test.go
+++ b/packet_packer_test.go
@@ -65,7 +65,7 @@ var _ = Describe("Packet packer", func() {
 	}
 
 	expectAppendStreamFrames := func(frames ...ackhandler.StreamFrame) {
-		framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(fs []ackhandler.StreamFrame, _ protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+		framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(fs []ackhandler.StreamFrame, _ protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 			var length protocol.ByteCount
 			for _, f := range frames {
 				length += f.Frame.Length(v)
@@ -75,7 +75,7 @@ var _ = Describe("Packet packer", func() {
 	}
 
 	expectAppendControlFrames := func(frames ...ackhandler.Frame) {
-		framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(fs []ackhandler.Frame, _ protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
+		framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(fs []ackhandler.Frame, _ protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
 			var length protocol.ByteCount
 			for _, f := range frames {
 				length += f.Frame.Length(v)
@@ -301,12 +301,12 @@ var _ = Describe("Packet packer", func() {
 				pnManager.EXPECT().PopPacketNumber(protocol.Encryption0RTT).Return(protocol.PacketNumber(0x42))
 				cf := ackhandler.Frame{Frame: &wire.MaxDataFrame{MaximumData: 0x1337}}
 				framer.EXPECT().HasData().Return(true)
-				framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(frames []ackhandler.Frame, _ protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
+				framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(frames []ackhandler.Frame, _ protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
 					Expect(frames).To(BeEmpty())
 					return append(frames, cf), cf.Frame.Length(v)
 				})
 				// TODO: check sizes
-				framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(frames []ackhandler.StreamFrame, _ protocol.ByteCount, _ protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+				framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(frames []ackhandler.StreamFrame, _ protocol.ByteCount, _ protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 					return frames, 0
 				})
 				p, err := packer.PackCoalescedPacket(false, maxPacketSize, protocol.Version1)
@@ -681,11 +681,11 @@ var _ = Describe("Packet packer", func() {
 				ackFramer.EXPECT().GetAckFrame(protocol.Encryption1RTT, false)
 				var maxSize protocol.ByteCount
 				gomock.InOrder(
-					framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(fs []ackhandler.Frame, maxLen protocol.ByteCount, _ protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
+					framer.EXPECT().AppendControlFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(fs []ackhandler.Frame, maxLen protocol.ByteCount, _ protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) {
 						maxSize = maxLen
 						return fs, 444
 					}),
-					framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).Do(func(fs []ackhandler.StreamFrame, maxLen protocol.ByteCount, _ protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+					framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).Do(func(fs []ackhandler.StreamFrame, maxLen protocol.ByteCount, _ protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 						Expect(maxLen).To(Equal(maxSize - 444))
 						return fs, 0
 					}),
@@ -1491,7 +1491,7 @@ var _ = Describe("Packet packer", func() {
 				pnManager.EXPECT().PopPacketNumber(protocol.Encryption1RTT).Return(protocol.PacketNumber(0x42))
 				framer.EXPECT().HasData().Return(true)
 				expectAppendControlFrames()
-				framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(fs []ackhandler.StreamFrame, maxSize protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
+				framer.EXPECT().AppendStreamFrames(gomock.Any(), gomock.Any(), protocol.Version1).DoAndReturn(func(fs []ackhandler.StreamFrame, maxSize protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) {
 					sf, split := f.MaybeSplitOffFrame(maxSize, v)
 					Expect(split).To(BeTrue())
 					return append(fs, ackhandler.StreamFrame{Frame: sf}), sf.Length(v)
diff --git a/qlog/packet_header_test.go b/qlog/packet_header_test.go
index 9d37e556..e4ed264a 100644
--- a/qlog/packet_header_test.go
+++ b/qlog/packet_header_test.go
@@ -39,7 +39,7 @@ var _ = Describe("Packet Header", func() {
 					Header: wire.Header{
 						Type:    protocol.PacketTypeInitial,
 						Length:  123,
-						Version: protocol.VersionNumber(0xdecafbad),
+						Version: protocol.Version(0xdecafbad),
 					},
 				},
 				map[string]interface{}{
@@ -59,7 +59,7 @@ var _ = Describe("Packet Header", func() {
 					Header: wire.Header{
 						Type:    protocol.PacketTypeInitial,
 						Length:  123,
-						Version: protocol.VersionNumber(0xdecafbad),
+						Version: protocol.Version(0xdecafbad),
 						Token:   []byte{0xde, 0xad, 0xbe, 0xef},
 					},
 				},
@@ -80,7 +80,7 @@ var _ = Describe("Packet Header", func() {
 					Header: wire.Header{
 						Type:            protocol.PacketTypeRetry,
 						SrcConnectionID: protocol.ParseConnectionID([]byte{0x11, 0x22, 0x33, 0x44}),
-						Version:         protocol.VersionNumber(0xdecafbad),
+						Version:         protocol.Version(0xdecafbad),
 						Token:           []byte{0xde, 0xad, 0xbe, 0xef},
 					},
 				},
@@ -101,7 +101,7 @@ var _ = Describe("Packet Header", func() {
 					PacketNumber: 0,
 					Header: wire.Header{
 						Type:    protocol.PacketTypeHandshake,
-						Version: protocol.VersionNumber(0xdecafbad),
+						Version: protocol.Version(0xdecafbad),
 					},
 				},
 				map[string]interface{}{
@@ -121,7 +121,7 @@ var _ = Describe("Packet Header", func() {
 					Header: wire.Header{
 						Type:            protocol.PacketTypeHandshake,
 						SrcConnectionID: protocol.ParseConnectionID([]byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}),
-						Version:         protocol.VersionNumber(0xdecafbad),
+						Version:         protocol.Version(0xdecafbad),
 					},
 				},
 				map[string]interface{}{
diff --git a/qlog/qlog_test.go b/qlog/qlog_test.go
index 7684fcc5..29de43e8 100644
--- a/qlog/qlog_test.go
+++ b/qlog/qlog_test.go
@@ -581,7 +581,7 @@ var _ = Describe("Tracing", func() {
 				tracer.ReceivedVersionNegotiationPacket(
 					protocol.ArbitraryLenConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
 					protocol.ArbitraryLenConnectionID{4, 3, 2, 1},
-					[]protocol.VersionNumber{0xdeadbeef, 0xdecafbad},
+					[]protocol.Version{0xdeadbeef, 0xdecafbad},
 				)
 				entry := exportAndParseSingle()
 				Expect(entry.Time).To(BeTemporally("~", time.Now(), scaleDuration(10*time.Millisecond)))
diff --git a/server_test.go b/server_test.go
index 7679034a..58b15921 100644
--- a/server_test.go
+++ b/server_test.go
@@ -125,8 +125,8 @@ var _ = Describe("Server", func() {
 	})
 
 	It("errors when the Config contains an invalid version", func() {
-		version := protocol.VersionNumber(0x1234)
-		_, err := Listen(nil, tlsConf, &Config{Versions: []protocol.VersionNumber{version}})
+		version := protocol.Version(0x1234)
+		_, err := Listen(nil, tlsConf, &Config{Versions: []protocol.Version{version}})
 		Expect(err).To(MatchError("invalid QUIC version: 0x1234"))
 	})
 
@@ -143,7 +143,7 @@ var _ = Describe("Server", func() {
 	})
 
 	It("setups with the right values", func() {
-		supportedVersions := []protocol.VersionNumber{protocol.Version1}
+		supportedVersions := []protocol.Version{protocol.Version1}
 		config := Config{
 			Versions:             supportedVersions,
 			HandshakeIdleTimeout: 1337 * time.Hour,
@@ -310,7 +310,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					Expect(origDestConnID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xad, 0xc0, 0xde})))
 					Expect(*retrySrcConnID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad})))
@@ -355,7 +355,7 @@ var _ = Describe("Server", func() {
 				}, make([]byte, protocol.MinUnknownVersionPacketSize))
 				raddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
 				packet.remoteAddr = raddr
-				tracer.EXPECT().SentVersionNegotiationPacket(packet.remoteAddr, gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ net.Addr, src, dest protocol.ArbitraryLenConnectionID, _ []protocol.VersionNumber) {
+				tracer.EXPECT().SentVersionNegotiationPacket(packet.remoteAddr, gomock.Any(), gomock.Any(), gomock.Any()).Do(func(_ net.Addr, src, dest protocol.ArbitraryLenConnectionID, _ []protocol.Version) {
 					Expect(src).To(Equal(protocol.ArbitraryLenConnectionID(destConnID.Bytes())))
 					Expect(dest).To(Equal(protocol.ArbitraryLenConnectionID(srcConnID.Bytes())))
 				})
@@ -367,7 +367,7 @@ var _ = Describe("Server", func() {
 					Expect(err).ToNot(HaveOccurred())
 					Expect(dest).To(Equal(protocol.ArbitraryLenConnectionID(srcConnID.Bytes())))
 					Expect(src).To(Equal(protocol.ArbitraryLenConnectionID(destConnID.Bytes())))
-					Expect(versions).ToNot(ContainElement(protocol.VersionNumber(0x42)))
+					Expect(versions).ToNot(ContainElement(protocol.Version(0x42)))
 					return len(b), nil
 				})
 				serv.handlePacket(packet)
@@ -395,7 +395,7 @@ var _ = Describe("Server", func() {
 				data := wire.ComposeVersionNegotiation(
 					protocol.ArbitraryLenConnectionID{1, 2, 3, 4},
 					protocol.ArbitraryLenConnectionID{4, 3, 2, 1},
-					[]protocol.VersionNumber{1, 2, 3},
+					[]protocol.Version{1, 2, 3},
 				)
 				raddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
 				done := make(chan struct{})
@@ -513,7 +513,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					Expect(origDestConnID).To(Equal(hdr.DestConnectionID))
 					Expect(retrySrcConnID).To(BeNil())
@@ -577,7 +577,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					<-acceptConn
 					counter.Add(1)
@@ -632,7 +632,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					createdConn = true
 					return NewMockQUICConn(mockCtrl)
@@ -683,7 +683,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					conn := <-connChan
 					conn.EXPECT().handlePacket(gomock.Any())
@@ -763,7 +763,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					conn := <-connChan
 					conn.EXPECT().handlePacket(gomock.Any())
@@ -1047,7 +1047,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					conn := NewMockQUICConn(mockCtrl)
 					conn.EXPECT().handlePacket(gomock.Any())
@@ -1117,7 +1117,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					Expect(conf.MaxIncomingStreams).To(BeEquivalentTo(1234))
 					conn.EXPECT().handlePacket(gomock.Any())
@@ -1194,7 +1194,7 @@ var _ = Describe("Server", func() {
 					_ *logging.ConnectionTracer,
 					_ uint64,
 					_ utils.Logger,
-					_ protocol.VersionNumber,
+					_ protocol.Version,
 				) quicConn {
 					conn.EXPECT().handlePacket(gomock.Any())
 					conn.EXPECT().HandshakeComplete().Return(handshakeChan)
@@ -1267,7 +1267,7 @@ var _ = Describe("Server", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				conn.EXPECT().handlePacket(gomock.Any())
 				conn.EXPECT().run()
@@ -1311,7 +1311,7 @@ var _ = Describe("Server", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				defer wg.Done()
 				ready := make(chan struct{})
@@ -1372,7 +1372,7 @@ var _ = Describe("Server", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				conn.EXPECT().handlePacket(p)
 				conn.EXPECT().run()
@@ -1495,7 +1495,7 @@ var _ = Describe("Server", func() {
 				_ *logging.ConnectionTracer,
 				_ uint64,
 				_ utils.Logger,
-				_ protocol.VersionNumber,
+				_ protocol.Version,
 			) quicConn {
 				conn := NewMockQUICConn(mockCtrl)
 				var calls []any
diff --git a/testutils/testutils.go b/testutils/testutils.go
index e06c8e6a..dd602d2d 100644
--- a/testutils/testutils.go
+++ b/testutils/testutils.go
@@ -21,7 +21,7 @@ func writePacket(hdr *wire.ExtendedHeader, data []byte) []byte {
 }
 
 // packRawPayload returns a new raw payload containing given frames
-func packRawPayload(version protocol.VersionNumber, frames []wire.Frame) []byte {
+func packRawPayload(version protocol.Version, frames []wire.Frame) []byte {
 	var b []byte
 	for _, cf := range frames {
 		var err error
@@ -39,7 +39,7 @@ func ComposeInitialPacket(
 	srcConnID, destConnID, key protocol.ConnectionID,
 	frames []wire.Frame,
 	sentBy protocol.Perspective,
-	version protocol.VersionNumber,
+	version protocol.Version,
 ) []byte {
 	sealer, _ := handshake.NewInitialAEAD(key, sentBy, version)
 
@@ -90,7 +90,7 @@ func ComposeRetryPacket(
 	destConnID protocol.ConnectionID,
 	origDestConnID protocol.ConnectionID,
 	token []byte,
-	version protocol.VersionNumber,
+	version protocol.Version,
 ) []byte {
 	hdr := &wire.ExtendedHeader{
 		Header: wire.Header{