Repository: libp2p/go-libp2p
Pull request #1723 (2022-08-28 14:27:39)

quic: update quic-go to v0.29.0


Patch:
diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md
index dbbb1b23..e23d61a5 100644
--- a/.github/ISSUE_TEMPLATE/release.md
+++ b/.github/ISSUE_TEMPLATE/release.md
@@ -19,39 +19,13 @@ about: 'Start a new libp2p release.'
 
 - [ ] **Stage 0 - Finishing Touches**
     - [ ] Go through relevant libp2p repos looking for unreleased changes that should make it into the release. If you find any, cut releases.
-    - [ ] Run `go get -u ./...` to see if there are any out-of-date deps that look important. If there are, bubble them. Try to avoid _directly_ updating indirect deps in go-libp2p's go.mod when possible.
-    - [ ] Make sure local tests are passing.
-- [ ] **Stage 1 - Upstream Testing**
-  - Create testing branches in lotus & go-ipfs with the new go-libp2p release and run CI/tests. Many upstream projects are tested in CI, but lotus & go-ipfs are not.
-    - [ ] [filecoin-project/lotus](https://github.com/filecoin-project/lotus)
-    - [ ] [ipfs/go-ipfs](https://github.com/ipfs/go-ipfs)
-  - _(someday)_ Run upstream testground tests. Unfortunately, this is too time consuming at the moment.
-    - _(someday)_ Run bitswap testground tests.
-    - _(someday)_ Run DHT testground tests.
-- [ ] **Stage 2 - Infrastructure Testing**
-  - How: Using the testing branches created above, work with the infrastructure team to deploy the new libp2p versions to our infrastructure.
-  - Where:
-    - [ ] A go-ipfs gateway.
-      - [ ] Deploy
-      - [ ] Analyze
-        - [ ] Look at pprof profile dumps, especially CPU profiles and heap allocation profiles, noting any significant changes.
-    - [ ] A go-ipfs bootstrapper.
-      - [ ] Deploy
-      - [ ] Analyze
-        - [ ] Look at pprof profile dumps, especially CPU profiles and heap allocation profiles, noting any significant changes.
-        - [ ] Check peers (e.g., `ipfs swarm peers`) to make sure we're connecting to peers on all transports.
-        - [ ] Check advertised addresses and protocols (e.g., `ipfs id`) to make sure they're sane.
-- [ ] **Stage 3 - Release**
-  - [ ] Tag the release on master.
+    - [ ] Run `go get -u ./...` to see if there are any out-of-date deps that look important. If there are, bubble them. Try to avoid _directly_ updating indirect deps in go-libp2p's `go.mod` when possible.
+- [ ] **Stage 1 - Release**
   - [ ] Publish the release through the GitHub UI, adding the release notes. Some users rely on this to receive notifications of new releases.
   - [ ] Announce the release on the [discuss.libp2p.io](https://discuss.libp2p.io).
-- [ ] **Stage 4 - Update Upstream**
+- [ ] **Stage 2 - Update Upstream**
   - [ ] Update the examples to the final release
-  - [ ] Update the upstream testing branches to the final release and create PRs.
+  - [ ] Update the upstream dependencies to the final release and create PRs.
     - [ ] [filecoin-project/lotus](https://github.com/filecoin-project/lotus)
-    - [ ] [ipfs/go-bitswap](https://github.com/ipfs/go-bitswap)
-    - [ ] [ipfs/go-ipfs](https://github.com/ipfs/go-ipfs)
-    - [ ] [libp2p/go-libp2p-kad-dht](https://github.com/libp2p/go-libp2p-kad-dht)
-    - [ ] [libp2p/go-libp2p-pubsub](https://github.com/libp2p/go-libp2p-pubsub)
-    - [ ] [libp2p/go-libp2p-daemon](https://github.com/libp2p/go-libp2p-daemon)
+    - [ ] [ipfs/kubo](https://github.com/ipfs/kubo)
 - [ ] Make required changes to the release process.
diff --git a/config/config.go b/config/config.go
index 4ccbc509..90fa9c16 100644
--- a/config/config.go
+++ b/config/config.go
@@ -64,6 +64,11 @@ type Config struct {
 	// Set it via the UserAgent option function.
 	UserAgent string
 
+	// ProtocolVersion is the protocol version that identifies the family
+	// of protocols used by the peer in the Identify protocol. It is set
+	// using the [ProtocolVersion] option.
+	ProtocolVersion string
+
 	PeerKey crypto.PrivKey
 
 	Transports         []TptC
@@ -223,6 +228,7 @@ func (cfg *Config) NewNode() (host.Host, error) {
 		NATManager:          cfg.NATManager,
 		EnablePing:          !cfg.DisablePing,
 		UserAgent:           cfg.UserAgent,
+		ProtocolVersion:     cfg.ProtocolVersion,
 		MultiaddrResolver:   cfg.MultiaddrResolver,
 		EnableHolePunching:  cfg.EnableHolePunching,
 		HolePunchingOptions: cfg.HolePunchingOptions,
diff --git a/go.mod b/go.mod
index 3e8806ab..64b2a600 100644
--- a/go.mod
+++ b/go.mod
@@ -31,7 +31,7 @@ require (
 	github.com/libp2p/go-reuseport v0.2.0
 	github.com/libp2p/go-yamux/v3 v3.1.2
 	github.com/libp2p/zeroconf/v2 v2.2.0
-	github.com/lucas-clemente/quic-go v0.28.1
+	github.com/lucas-clemente/quic-go v0.29.0
 	github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd
 	github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b
 	github.com/minio/sha256-simd v1.0.0
@@ -60,7 +60,6 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash v1.1.0 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
-	github.com/cheekybits/genny v1.0.0 // indirect
 	github.com/containerd/cgroups v1.0.4 // indirect
 	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
@@ -82,8 +81,6 @@ require (
 	github.com/klauspost/cpuid/v2 v2.1.0 // indirect
 	github.com/koron/go-ssdp v0.0.3 // indirect
 	github.com/libp2p/go-cidranger v1.1.0 // indirect
-	github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
-	github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
 	github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
 	github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
 	github.com/mattn/go-isatty v0.0.16 // indirect
@@ -107,6 +104,7 @@ require (
 	go.uber.org/atomic v1.10.0 // indirect
 	go.uber.org/multierr v1.8.0 // indirect
 	go.uber.org/zap v1.22.0 // indirect
+	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
 	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
 	golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
 	golang.org/x/tools v0.1.12 // indirect
diff --git a/go.sum b/go.sum
index 2049a41b..402c81cf 100644
--- a/go.sum
+++ b/go.sum
@@ -66,8 +66,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
-github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -318,19 +316,13 @@ github.com/libp2p/go-yamux/v3 v3.1.2 h1:lNEy28MBk1HavUAlzKgShp+F6mn/ea1nDYWftZhF
 github.com/libp2p/go-yamux/v3 v3.1.2/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4=
 github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q=
 github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs=
-github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU=
-github.com/lucas-clemente/quic-go v0.28.1/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0=
+github.com/lucas-clemente/quic-go v0.29.0 h1:Vw0mGTfmWqGzh4jx/kMymsIkFK6rErFVmg+t9RLrnZE=
+github.com/lucas-clemente/quic-go v0.29.0/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE=
 github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
-github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
-github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
-github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
-github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
 github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
 github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
-github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
 github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU=
 github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
@@ -401,16 +393,12 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
-github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
-github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
-github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
 github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
 github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
@@ -556,7 +544,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
@@ -572,6 +559,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
+golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -637,12 +626,10 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E=
 golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -708,7 +695,6 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -729,7 +715,6 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/options.go b/options.go
index 6ed6a94d..3509c61d 100644
--- a/options.go
+++ b/options.go
@@ -414,6 +414,15 @@ var NoTransports = func(cfg *Config) error {
 	return nil
 }
 
+// ProtocolVersion sets the protocolVersion string required by the
+// libp2p Identify protocol.
+func ProtocolVersion(s string) Option {
+	return func(cfg *Config) error {
+		cfg.ProtocolVersion = s
+		return nil
+	}
+}
+
 // UserAgent sets the libp2p user-agent sent along with the identify protocol
 func UserAgent(userAgent string) Option {
 	return func(cfg *Config) error {
diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go
index d3642bd8..99978763 100644
--- a/p2p/host/basic/basic_host.go
+++ b/p2p/host/basic/basic_host.go
@@ -145,6 +145,9 @@ type HostOpts struct {
 	// UserAgent sets the user-agent for the host.
 	UserAgent string
 
+	// ProtocolVersion sets the protocol version for the host.
+	ProtocolVersion string
+
 	// DisableSignedPeerRecord disables the generation of Signed Peer Records on this host.
 	DisableSignedPeerRecord bool
 
@@ -226,9 +229,18 @@ func NewHost(n network.Network, opts *HostOpts) (*BasicHost, error) {
 
 	// we can't set this as a default above because it depends on the *BasicHost.
 	if h.disableSignedPeerRecord {
-		h.ids, err = identify.NewIDService(h, identify.UserAgent(opts.UserAgent), identify.DisableSignedPeerRecord())
+		h.ids, err = identify.NewIDService(
+			h,
+			identify.UserAgent(opts.UserAgent),
+			identify.ProtocolVersion(opts.ProtocolVersion),
+			identify.DisableSignedPeerRecord(),
+		)
 	} else {
-		h.ids, err = identify.NewIDService(h, identify.UserAgent(opts.UserAgent))
+		h.ids, err = identify.NewIDService(
+			h,
+			identify.UserAgent(opts.UserAgent),
+			identify.ProtocolVersion(opts.ProtocolVersion),
+		)
 	}
 	if err != nil {
 		return nil, fmt.Errorf("failed to create Identify service: %s", err)
diff --git a/p2p/host/resource-manager/scope.go b/p2p/host/resource-manager/scope.go
index 872f0eb6..2a83c695 100644
--- a/p2p/host/resource-manager/scope.go
+++ b/p2p/host/resource-manager/scope.go
@@ -2,6 +2,8 @@ package rcmgr
 
 import (
 	"fmt"
+	"math"
+	"math/big"
 	"strings"
 	"sync"
 
@@ -79,14 +81,55 @@ func IsSpan(name string) bool {
 	return strings.Contains(name, ".span-")
 }
 
+func addInt64WithOverflow(a int64, b int64) (c int64, ok bool) {
+	c = a + b
+	return c, (c > a) == (b > 0)
+}
+
+// mulInt64WithOverflow checks for overflow in multiplying two int64s. See
+// https://groups.google.com/g/golang-nuts/c/h5oSN5t3Au4/m/KaNQREhZh0QJ
+func mulInt64WithOverflow(a, b int64) (c int64, ok bool) {
+	const mostPositive = 1<<63 - 1
+	const mostNegative = -(mostPositive + 1)
+	c = a * b
+	if a == 0 || b == 0 || a == 1 || b == 1 {
+		return c, true
+	}
+	if a == mostNegative || b == mostNegative {
+		return c, false
+	}
+	return c, c/b == a
+}
+
 // Resources implementation
 func (rc *resources) checkMemory(rsvp int64, prio uint8) error {
-	// overflow check; this also has the side effect that we cannot reserve negative memory.
-	newmem := rc.memory + rsvp
+	if rsvp < 0 {
+		return fmt.Errorf("can't reserve negative memory. rsvp=%v", rsvp)
+	}
+
 	limit := rc.limit.GetMemoryLimit()
-	threshold := (1 + int64(prio)) * limit / 256
+	if limit == math.MaxInt64 {
+		// Special case where we've set max limits.
+		return nil
+	}
+
+	newmem, addOk := addInt64WithOverflow(rc.memory, rsvp)
+
+	threshold, mulOk := mulInt64WithOverflow(1+int64(prio), limit)
+	if !mulOk {
+		thresholdBig := big.NewInt(limit)
+		thresholdBig = thresholdBig.Mul(thresholdBig, big.NewInt(1+int64(prio)))
+		thresholdBig.Rsh(thresholdBig, 8) // Divide 256
+		if !thresholdBig.IsInt64() {
+			// Shouldn't happen since the threshold can only be <= limit
+			threshold = limit
+		}
+		threshold = thresholdBig.Int64()
+	} else {
+		threshold = threshold / 256
+	}
 
-	if newmem > threshold {
+	if !addOk || newmem > threshold {
 		return &errMemoryLimitExceeded{
 			current:   rc.memory,
 			attempted: rsvp,
diff --git a/p2p/protocol/identify/id.go b/p2p/protocol/identify/id.go
index 4794619d..b9d95240 100644
--- a/p2p/protocol/identify/id.go
+++ b/p2p/protocol/identify/id.go
@@ -33,11 +33,7 @@ var log = logging.Logger("net/identify")
 // service.
 const ID = "/ipfs/id/1.0.0"
 
-// LibP2PVersion holds the current protocol version for a client running this code
-// TODO(jbenet): fix the versioning mess.
-// XXX: Don't change this till 2020. You'll break all go-ipfs versions prior to
-// 0.4.17 which asserted an exact version match.
-const LibP2PVersion = "ipfs/0.1.0"
+const DefaultProtocolVersion = "ipfs/0.1.0"
 
 const ServiceName = "libp2p.identify"
 
@@ -89,8 +85,9 @@ type IDService interface {
 //   - Our IPFS Agent Version
 //   - Our public Listen Addresses
 type idService struct {
-	Host      host.Host
-	UserAgent string
+	Host            host.Host
+	UserAgent       string
+	ProtocolVersion string
 
 	ctx       context.Context
 	ctxCancel context.CancelFunc
@@ -135,9 +132,15 @@ func NewIDService(h host.Host, opts ...Option) (*idService, error) {
 		userAgent = cfg.userAgent
 	}
 
+	protocolVersion := DefaultProtocolVersion
+	if cfg.protocolVersion != "" {
+		protocolVersion = cfg.protocolVersion
+	}
+
 	s := &idService{
-		Host:      h,
-		UserAgent: userAgent,
+		Host:            h,
+		UserAgent:       userAgent,
+		ProtocolVersion: protocolVersion,
 
 		conns: make(map[network.Conn]chan struct{}),
 
@@ -188,8 +191,10 @@ func (ids *idService) loop() {
 	defer ids.refCount.Done()
 
 	phs := make(map[peer.ID]*peerHandler)
-	sub, err := ids.Host.EventBus().Subscribe([]interface{}{&event.EvtLocalProtocolsUpdated{},
-		&event.EvtLocalAddressesUpdated{}}, eventbus.BufSize(256))
+	sub, err := ids.Host.EventBus().Subscribe([]interface{}{
+		&event.EvtLocalProtocolsUpdated{},
+		&event.EvtLocalAddressesUpdated{},
+	}, eventbus.BufSize(256))
 	if err != nil {
 		log.Errorf("failed to subscribe to events on the bus, err=%s", err)
 		return
@@ -489,7 +494,6 @@ func (ids *idService) writeChunkedIdentifyMsg(c network.Conn, snapshot *identify
 	m := &pb.Identify{SignedPeerRecord: sr}
 	err := writer.WriteMsg(m)
 	return err
-
 }
 
 func (ids *idService) createBaseIdentifyResponse(
@@ -541,10 +545,8 @@ func (ids *idService) createBaseIdentifyResponse(
 	}
 
 	// set protocol versions
-	pv := LibP2PVersion
-	av := ids.UserAgent
-	mes.ProtocolVersion = &pv
-	mes.AgentVersion = &av
+	mes.ProtocolVersion = &ids.ProtocolVersion
+	mes.AgentVersion = &ids.UserAgent
 
 	return mes
 }
diff --git a/p2p/protocol/identify/opts.go b/p2p/protocol/identify/opts.go
index 0eb1d966..38f505b6 100644
--- a/p2p/protocol/identify/opts.go
+++ b/p2p/protocol/identify/opts.go
@@ -1,6 +1,7 @@
 package identify
 
 type config struct {
+	protocolVersion         string
 	userAgent               string
 	disableSignedPeerRecord bool
 }
@@ -8,6 +9,14 @@ type config struct {
 // Option is an option function for identify.
 type Option func(*config)
 
+// ProtocolVersion sets the protocol version string that will be used to
+// identify the family of protocols used by the peer.
+func ProtocolVersion(s string) Option {
+	return func(cfg *config) {
+		cfg.protocolVersion = s
+	}
+}
+
 // UserAgent sets the user agent this node will identify itself with to peers.
 func UserAgent(ua string) Option {
 	return func(cfg *config) {
diff --git a/p2p/security/noise/handshake.go b/p2p/security/noise/handshake.go
index b71d7ef8..bb68196c 100644
--- a/p2p/security/noise/handshake.go
+++ b/p2p/security/noise/handshake.go
@@ -10,17 +10,16 @@ import (
 	"runtime/debug"
 	"time"
 
-	"github.com/minio/sha256-simd"
 	"golang.org/x/crypto/chacha20poly1305"
 
-	"github.com/libp2p/go-libp2p/p2p/security/noise/pb"
-
 	"github.com/libp2p/go-libp2p/core/crypto"
 	"github.com/libp2p/go-libp2p/core/peer"
+	"github.com/libp2p/go-libp2p/p2p/security/noise/pb"
 
 	"github.com/flynn/noise"
 	"github.com/gogo/protobuf/proto"
 	pool "github.com/libp2p/go-buffer-pool"
+	"github.com/minio/sha256-simd"
 )
 
 // payloadSigPrefix is prepended to our Noise static key before signing with
@@ -89,10 +88,12 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
 
 	if s.initiator {
 		// stage 0 //
-		// do not send the payload just yet, as it would be plaintext; not secret.
 		// Handshake Msg Len = len(DH ephemeral key)
-		err = s.sendHandshakeMessage(hs, nil, hbuf)
-		if err != nil {
+		var ed []byte
+		if s.earlyDataHandler != nil {
+			ed = s.earlyDataHandler.Send(ctx, s.insecureConn, s.remoteID)
+		}
+		if err := s.sendHandshakeMessage(hs, ed, hbuf); err != nil {
 			return fmt.Errorf("error sending handshake message: %w", err)
 		}
 
@@ -101,29 +102,34 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
 		if err != nil {
 			return fmt.Errorf("error reading handshake message: %w", err)
 		}
-		err = s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic())
-		if err != nil {
+		if err := s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic()); err != nil {
 			return err
 		}
 
 		// stage 2 //
 		// Handshake Msg Len = len(DHT static key) +  MAC(static key is encrypted) + len(Payload) + MAC(payload is encrypted)
-		err = s.sendHandshakeMessage(hs, payload, hbuf)
-		if err != nil {
+		if err := s.sendHandshakeMessage(hs, payload, hbuf); err != nil {
 			return fmt.Errorf("error sending handshake message: %w", err)
 		}
+		return nil
 	} else {
 		// stage 0 //
-		// We don't expect any payload on the first message.
-		if _, err := s.readHandshakeMessage(hs); err != nil {
+		initialPayload, err := s.readHandshakeMessage(hs)
+		if err != nil {
 			return fmt.Errorf("error reading handshake message: %w", err)
 		}
+		if s.earlyDataHandler != nil {
+			if err := s.earlyDataHandler.Received(ctx, s.insecureConn, initialPayload); err != nil {
+				return err
+			}
+		} else if len(initialPayload) > 0 {
+			return fmt.Errorf("received unexpected early data (%d bytes)", len(initialPayload))
+		}
 
 		// stage 1 //
 		// Handshake Msg Len = len(DH ephemeral key) + len(DHT static key) +  MAC(static key is encrypted) + len(Payload) +
 		// MAC(payload is encrypted)
-		err = s.sendHandshakeMessage(hs, payload, hbuf)
-		if err != nil {
+		if err := s.sendHandshakeMessage(hs, payload, hbuf); err != nil {
 			return fmt.Errorf("error sending handshake message: %w", err)
 		}
 
@@ -132,13 +138,8 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
 		if err != nil {
 			return fmt.Errorf("error reading handshake message: %w", err)
 		}
-		err = s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic())
-		if err != nil {
-			return err
-		}
+		return s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic())
 	}
-
-	return nil
 }
 
 // setCipherStates sets the initial cipher states that will be used to protect
diff --git a/p2p/security/noise/session.go b/p2p/security/noise/session.go
index a563e58b..5e3d0956 100644
--- a/p2p/security/noise/session.go
+++ b/p2p/security/noise/session.go
@@ -36,20 +36,22 @@ type secureSession struct {
 	dec *noise.CipherState
 
 	// noise prologue
-	prologue []byte
+	prologue         []byte
+	earlyDataHandler EarlyDataHandler
 }
 
 // newSecureSession creates a Noise session over the given insecureConn Conn, using
 // the libp2p identity keypair from the given Transport.
-func newSecureSession(tpt *Transport, ctx context.Context, insecure net.Conn, remote peer.ID, prologue []byte, initiator bool) (*secureSession, error) {
+func newSecureSession(tpt *Transport, ctx context.Context, insecure net.Conn, remote peer.ID, prologue []byte, edh EarlyDataHandler, initiator bool) (*secureSession, error) {
 	s := &secureSession{
-		insecureConn:   insecure,
-		insecureReader: bufio.NewReader(insecure),
-		initiator:      initiator,
-		localID:        tpt.localID,
-		localKey:       tpt.privateKey,
-		remoteID:       remote,
-		prologue:       prologue,
+		insecureConn:     insecure,
+		insecureReader:   bufio.NewReader(insecure),
+		initiator:        initiator,
+		localID:          tpt.localID,
+		localKey:         tpt.privateKey,
+		remoteID:         remote,
+		prologue:         prologue,
+		earlyDataHandler: edh,
 	}
 
 	// the go-routine we create to run the handshake will
diff --git a/p2p/security/noise/session_transport.go b/p2p/security/noise/session_transport.go
index b4414136..973f6fac 100644
--- a/p2p/security/noise/session_transport.go
+++ b/p2p/security/noise/session_transport.go
@@ -12,6 +12,32 @@ import (
 
 type SessionOption = func(*SessionTransport) error
 
+// Prologue sets a prologue for the Noise session.
+// The handshake will only complete successfully if both parties set the same prologue.
+// See https://noiseprotocol.org/noise.html#prologue for details.
+func Prologue(prologue []byte) SessionOption {
+	return func(s *SessionTransport) error {
+		s.prologue = prologue
+		return nil
+	}
+}
+
+// EarlyDataHandler allows attaching an (unencrypted) application payload to the first handshake message.
+// While unencrypted, the integrity of this early data is retroactively authenticated on completion of the handshake.
+type EarlyDataHandler interface {
+	// Send is called for the client before sending the first handshake message.
+	Send(context.Context, net.Conn, peer.ID) []byte
+	// Received is called for the server when the first handshake message from the client is received.
+	Received(context.Context, net.Conn, []byte) error
+}
+
+func EarlyData(h EarlyDataHandler) SessionOption {
+	return func(s *SessionTransport) error {
+		s.earlyDataHandler = h
+		return nil
+	}
+}
+
 var _ sec.SecureTransport = &SessionTransport{}
 
 // SessionTransport can be used
@@ -19,13 +45,14 @@ var _ sec.SecureTransport = &SessionTransport{}
 type SessionTransport struct {
 	t *Transport
 	// options
-	prologue []byte
+	prologue         []byte
+	earlyDataHandler EarlyDataHandler
 }
 
 // SecureInbound runs the Noise handshake as the responder.
 // If p is empty, connections from any peer are accepted.
 func (i *SessionTransport) SecureInbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
-	c, err := newSecureSession(i.t, ctx, insecure, p, i.prologue, false)
+	c, err := newSecureSession(i.t, ctx, insecure, p, i.prologue, i.earlyDataHandler, false)
 	if err != nil {
 		addr, maErr := manet.FromNetAddr(insecure.RemoteAddr())
 		if maErr == nil {
@@ -37,22 +64,5 @@ func (i *SessionTransport) SecureInbound(ctx context.Context, insecure net.Conn,
 
 // SecureOutbound runs the Noise handshake as the initiator.
 func (i *SessionTransport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
-	return newSecureSession(i.t, ctx, insecure, p, i.prologue, true)
-}
-
-func (t *Transport) WithSessionOptions(opts ...SessionOption) (sec.SecureTransport, error) {
-	st := &SessionTransport{t: t}
-	for _, opt := range opts {
-		if err := opt(st); err != nil {
-			return nil, err
-		}
-	}
-	return st, nil
-}
-
-func Prologue(prologue []byte) SessionOption {
-	return func(s *SessionTransport) error {
-		s.prologue = prologue
-		return nil
-	}
+	return newSecureSession(i.t, ctx, insecure, p, i.prologue, i.earlyDataHandler, true)
 }
diff --git a/p2p/security/noise/transport.go b/p2p/security/noise/transport.go
index f935b82a..bd66d0fd 100644
--- a/p2p/security/noise/transport.go
+++ b/p2p/security/noise/transport.go
@@ -41,7 +41,7 @@ func New(privkey crypto.PrivKey) (*Transport, error) {
 // SecureInbound runs the Noise handshake as the responder.
 // If p is empty, connections from any peer are accepted.
 func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
-	c, err := newSecureSession(t, ctx, insecure, p, nil, false)
+	c, err := newSecureSession(t, ctx, insecure, p, nil, nil, false)
 	if err != nil {
 		addr, maErr := manet.FromNetAddr(insecure.RemoteAddr())
 		if maErr == nil {
@@ -53,5 +53,15 @@ func (t *Transport) SecureInbound(ctx context.Context, insecure net.Conn, p peer
 
 // SecureOutbound runs the Noise handshake as the initiator.
 func (t *Transport) SecureOutbound(ctx context.Context, insecure net.Conn, p peer.ID) (sec.SecureConn, error) {
-	return newSecureSession(t, ctx, insecure, p, nil, true)
+	return newSecureSession(t, ctx, insecure, p, nil, nil, true)
+}
+
+func (t *Transport) WithSessionOptions(opts ...SessionOption) (sec.SecureTransport, error) {
+	st := &SessionTransport{t: t}
+	for _, opt := range opts {
+		if err := opt(st); err != nil {
+			return nil, err
+		}
+	}
+	return st, nil
 }
diff --git a/p2p/transport/quic/tracer_metrics.go b/p2p/transport/quic/tracer_metrics.go
index cbf2701f..624139fc 100644
--- a/p2p/transport/quic/tracer_metrics.go
+++ b/p2p/transport/quic/tracer_metrics.go
@@ -167,7 +167,9 @@ func init() {
 	prometheus.MustRegister(collector)
 }
 
-type metricsTracer struct{}
+type metricsTracer struct {
+	logging.NullTracer
+}
 
 var _ logging.Tracer = &metricsTracer{}
 
@@ -179,10 +181,9 @@ func (m *metricsTracer) SentPacket(_ net.Addr, _ *logging.Header, size logging.B
 	bytesTransferred.WithLabelValues("sent").Add(float64(size))
 }
 
-func (m *metricsTracer) DroppedPacket(addr net.Addr, packetType logging.PacketType, count logging.ByteCount, reason logging.PacketDropReason) {
-}
-
 type metricsConnTracer struct {
+	logging.NullConnectionTracer
+
 	perspective       logging.Perspective
 	startTime         time.Time
 	connID            logging.ConnectionID
@@ -224,9 +225,6 @@ func (m *metricsConnTracer) StartedConnection(net.Addr, net.Addr, logging.Connec
 	collector.AddConn(m.connID.String(), m)
 }
 
-func (m *metricsConnTracer) NegotiatedVersion(chosen quic.VersionNumber, clientVersions []quic.VersionNumber, serverVersions []quic.VersionNumber) {
-}
-
 func (m *metricsConnTracer) ClosedConnection(e error) {
 	var (
 		applicationErr      *quic.ApplicationError
@@ -264,9 +262,6 @@ func (m *metricsConnTracer) ClosedConnection(e error) {
 	}
 	connErrors.WithLabelValues(side, desc).Inc()
 }
-func (m *metricsConnTracer) SentTransportParameters(parameters *logging.TransportParameters)     {}
-func (m *metricsConnTracer) ReceivedTransportParameters(parameters *logging.TransportParameters) {}
-func (m *metricsConnTracer) RestoredTransportParameters(parameters *logging.TransportParameters) {}
 func (m *metricsConnTracer) SentPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, _ *logging.AckFrame, _ []logging.Frame) {
 	bytesTransferred.WithLabelValues("sent").Add(float64(size))
 	sentPackets.WithLabelValues(m.getEncLevel(logging.PacketTypeFromHeader(&hdr.Header))).Inc()
@@ -329,8 +324,6 @@ func (m *metricsConnTracer) UpdatedMetrics(rttStats *logging.RTTStats, cwnd, byt
 	m.mutex.Unlock()
 }
 
-func (m *metricsConnTracer) AcknowledgedPacket(logging.EncryptionLevel, logging.PacketNumber) {}
-
 func (m *metricsConnTracer) LostPacket(level logging.EncryptionLevel, _ logging.PacketNumber, r logging.PacketLossReason) {
 	var reason string
 	switch r {
@@ -344,23 +337,11 @@ func (m *metricsConnTracer) LostPacket(level logging.EncryptionLevel, _ logging.
 	lostPackets.WithLabelValues(level.String(), reason).Inc()
 }
 
-func (m *metricsConnTracer) UpdatedCongestionState(state logging.CongestionState) {}
-func (m *metricsConnTracer) UpdatedPTOCount(value uint32)                         {}
-func (m *metricsConnTracer) UpdatedKeyFromTLS(level logging.EncryptionLevel, perspective logging.Perspective) {
-}
-func (m *metricsConnTracer) UpdatedKey(generation logging.KeyPhase, remote bool) {}
 func (m *metricsConnTracer) DroppedEncryptionLevel(level logging.EncryptionLevel) {
 	if level == logging.EncryptionHandshake {
 		m.handleHandshakeComplete()
 	}
 }
-func (m *metricsConnTracer) DroppedKey(generation logging.KeyPhase) {}
-func (m *metricsConnTracer) SetLossTimer(timerType logging.TimerType, level logging.EncryptionLevel, time time.Time) {
-}
-
-func (m *metricsConnTracer) LossTimerExpired(timerType logging.TimerType, level logging.EncryptionLevel) {
-}
-func (m *metricsConnTracer) LossTimerCanceled() {}
 
 func (m *metricsConnTracer) Close() {
 	if m.handshakeComplete {
@@ -371,8 +352,6 @@ func (m *metricsConnTracer) Close() {
 	collector.RemoveConn(m.connID.String())
 }
 
-func (m *metricsConnTracer) Debug(name, msg string) {}
-
 func (m *metricsConnTracer) handleHandshakeComplete() {
 	m.handshakeComplete = true
 	newConns.WithLabelValues(m.getDirection(), "true").Inc()
diff --git a/p2p/transport/quic/transport.go b/p2p/transport/quic/transport.go
index 1ed3b05f..0b908db4 100644
--- a/p2p/transport/quic/transport.go
+++ b/p2p/transport/quic/transport.go
@@ -43,9 +43,9 @@ var quicConfig = &quic.Config{
 	MaxIncomingUniStreams:      -1,             // disable unidirectional streams
 	MaxStreamReceiveWindow:     10 * (1 << 20), // 10 MB
 	MaxConnectionReceiveWindow: 15 * (1 << 20), // 15 MB
-	AcceptToken: func(clientAddr net.Addr, _ *quic.Token) bool {
-		// TODO(#6): require source address validation when under load
-		return true
+	RequireAddressValidation: func(net.Addr) bool {
+		// TODO(#1535): require source address validation when under load
+		return false
 	},
 	KeepAlivePeriod: 15 * time.Second,
 	Versions:        []quic.VersionNumber{quic.VersionDraft29, quic.Version1},


Test patch:
diff --git a/.github/workflows/interop-test.yml b/.github/workflows/interop-test.yml
index 06134982..6f7486f1 100644
--- a/.github/workflows/interop-test.yml
+++ b/.github/workflows/interop-test.yml
@@ -2,15 +2,22 @@ on: [push, pull_request]
 name: Interoperability Testing
 
 jobs:
+  # NOTE: during a pull request run, github creates a merge commit referenced in `github.sha`
+  # that merge commit is not a regular commit. You won't find it with a regular `git checkout SHA` and
+  # tools like `go get repo@SHA` won't find it.
+  #
+  # As a workaround, we generate a path to the actual pull request's commit, it looks like:
+  # `github.com/external-org/go-libp2p@latest-commit-on-their-branch`
   run-ping-interop-cross-version:
     uses: "libp2p/test-plans/.github/workflows/run-composition.yml@master"
     with:
       composition_file: "ping/_compositions/go-cross-versions.toml"
-      # NOTE: during a pull request run, github creates a merge commit referenced in `github.sha`
-      # that merge commit is not a regular commit. You won't find it with a regular `git checkout SHA` and
-      # tools like `go get repo@SHA` won't find it.
-      #
-      # As a workaround, we generate a path to the actual pull request's commit, it looks like:
-      # `github.com/external-org/go-libp2p@latest-commit-on-their-branch`
       custom_git_target: github.com/${{ github.event.pull_request.head.repo.full_name || github.event.repository.full_name }}
       custom_git_reference: ${{ github.event.pull_request.head.sha || github.sha }}
+  run-ping-interop-cross-implementation:
+    uses: "libp2p/test-plans/.github/workflows/run-composition.yml@master"
+    with:
+      composition_file: "ping/_compositions/go-rust-interop-latest.toml"
+      custom_git_target: github.com/${{ github.event.pull_request.head.repo.full_name || github.event.repository.full_name }}
+      custom_git_reference: ${{ github.event.pull_request.head.sha || github.sha }}
+      custom_interop_target: go
\ No newline at end of file
diff --git a/p2p/host/resource-manager/scope_test.go b/p2p/host/resource-manager/scope_test.go
index af192a7b..0464cb0c 100644
--- a/p2p/host/resource-manager/scope_test.go
+++ b/p2p/host/resource-manager/scope_test.go
@@ -1,9 +1,12 @@
 package rcmgr
 
 import (
+	"math"
 	"testing"
+	"testing/quick"
 
 	"github.com/libp2p/go-libp2p/core/network"
+	"github.com/stretchr/testify/require"
 )
 
 func checkResources(t *testing.T, rc *resources, st network.ScopeStat) {
@@ -29,6 +32,77 @@ func checkResources(t *testing.T, rc *resources, st network.ScopeStat) {
 	}
 }
 
+func TestCheckMemory(t *testing.T) {
+	t.Run("overflows", func(t *testing.T) {
+		rc := resources{limit: &BaseLimit{
+			Memory:          math.MaxInt64 - 1,
+			StreamsInbound:  1,
+			StreamsOutbound: 1,
+			Streams:         1,
+			ConnsInbound:    1,
+			ConnsOutbound:   1,
+			Conns:           1,
+			FD:              1,
+		}}
+		rc.memory = math.MaxInt64 - 1
+		require.Error(t, rc.checkMemory(2, network.ReservationPriorityAlways))
+
+		rc.memory = 1024
+		require.NoError(t, rc.checkMemory(1, network.ReservationPriorityAlways))
+	})
+
+	t.Run("negative mem", func(t *testing.T) {
+		rc := resources{limit: &BaseLimit{
+			Memory:          math.MaxInt64,
+			StreamsInbound:  1,
+			StreamsOutbound: 1,
+			Streams:         1,
+			ConnsInbound:    1,
+			ConnsOutbound:   1,
+			Conns:           1,
+			FD:              1,
+		}}
+		rc.memory = math.MaxInt64
+
+		require.Error(t, rc.checkMemory(-1, network.ReservationPriorityAlways))
+	})
+
+	f := func(limit uint64, res uint64, currentMem uint64, priShift uint8) bool {
+		limit = (limit % math.MaxInt64) + 1
+		if limit < 1024 {
+			// We set the min to 1KiB
+			limit = 1024
+		}
+		currentMem = (currentMem % limit) // We can't have reserved more than our limit
+		res = (res >> 14)                 // We won't resonably ever have a reservation > 2^50
+		rc := resources{limit: &BaseLimit{
+			Memory:          int64(limit),
+			StreamsInbound:  1,
+			StreamsOutbound: 1,
+			Streams:         1,
+			ConnsInbound:    1,
+			ConnsOutbound:   1,
+			Conns:           1,
+			FD:              1,
+		}}
+		rc.memory = int64(currentMem)
+
+		priShift = (priShift % 9)
+		// Check different priorties at 2^0, 2^1,...2^8. This lets our math be correct in the check below (and avoid overflows).
+		pri := uint8((1 << priShift) - 1)
+
+		err := rc.checkMemory(int64(res), pri)
+		if limit == math.MaxInt64 && err == nil {
+			// Special case logic
+			return true
+		}
+
+		return (err != nil) == (uint64(res)+uint64(rc.memory) > (uint64(limit) >> uint64(8-priShift)))
+	}
+
+	require.NoError(t, quick.Check(f, nil))
+}
+
 func TestResources(t *testing.T) {
 	rc := resources{limit: &BaseLimit{
 		Memory:          4096,
diff --git a/p2p/protocol/identify/id_test.go b/p2p/protocol/identify/id_test.go
index d86fc915..ebdb6349 100644
--- a/p2p/protocol/identify/id_test.go
+++ b/p2p/protocol/identify/id_test.go
@@ -75,7 +75,7 @@ func testHasProtocolVersions(t *testing.T, h host.Host, p peer.ID) {
 		t.Error("no protocol version")
 		return
 	}
-	if v.(string) != identify.LibP2PVersion {
+	if v.(string) != identify.DefaultProtocolVersion {
 		t.Error("protocol mismatch", err)
 	}
 	v, err = h.Peerstore().Get(p, "AgentVersion")
diff --git a/p2p/security/noise/crypto_test.go b/p2p/security/noise/crypto_test.go
index 35837a5a..9b7d3908 100644
--- a/p2p/security/noise/crypto_test.go
+++ b/p2p/security/noise/crypto_test.go
@@ -93,7 +93,7 @@ func TestCryptoFailsIfHandshakeIncomplete(t *testing.T) {
 	init, resp := net.Pipe()
 	_ = resp.Close()
 
-	session, _ := newSecureSession(initTransport, context.TODO(), init, "remote-peer", nil, true)
+	session, _ := newSecureSession(initTransport, context.TODO(), init, "remote-peer", nil, nil, true)
 	_, err := session.encrypt(nil, []byte("hi"))
 	if err == nil {
 		t.Error("expected encryption error when handshake incomplete")
diff --git a/p2p/security/noise/transport_test.go b/p2p/security/noise/transport_test.go
index 5269be29..108efec8 100644
--- a/p2p/security/noise/transport_test.go
+++ b/p2p/security/noise/transport_test.go
@@ -78,10 +78,10 @@ func connect(t *testing.T, initTransport, respTransport *Transport) (*secureSess
 	done := make(chan struct{})
 	go func() {
 		defer close(done)
-		initConn, initErr = initTransport.SecureOutbound(context.TODO(), init, respTransport.localID)
+		initConn, initErr = initTransport.SecureOutbound(context.Background(), init, respTransport.localID)
 	}()
 
-	respConn, respErr := respTransport.SecureInbound(context.TODO(), resp, "")
+	respConn, respErr := respTransport.SecureInbound(context.Background(), resp, "")
 	<-done
 
 	if initErr != nil {
@@ -171,7 +171,7 @@ func TestPeerIDMatch(t *testing.T) {
 	done := make(chan struct{})
 	go func() {
 		defer close(done)
-		conn, err := initTransport.SecureOutbound(context.TODO(), init, respTransport.localID)
+		conn, err := initTransport.SecureOutbound(context.Background(), init, respTransport.localID)
 		assert.NoError(t, err)
 		assert.Equal(t, conn.RemotePeer(), respTransport.localID)
 		b := make([]byte, 6)
@@ -180,7 +180,7 @@ func TestPeerIDMatch(t *testing.T) {
 		assert.Equal(t, b, []byte("foobar"))
 	}()
 
-	conn, err := respTransport.SecureInbound(context.TODO(), resp, initTransport.localID)
+	conn, err := respTransport.SecureInbound(context.Background(), resp, initTransport.localID)
 	require.NoError(t, err)
 	require.Equal(t, conn.RemotePeer(), initTransport.localID)
 	_, err = conn.Write([]byte("foobar"))
@@ -194,11 +194,11 @@ func TestPeerIDMismatchOutboundFailsHandshake(t *testing.T) {
 
 	errChan := make(chan error)
 	go func() {
-		_, err := initTransport.SecureOutbound(context.TODO(), init, "a-random-peer-id")
+		_, err := initTransport.SecureOutbound(context.Background(), init, "a-random-peer-id")
 		errChan <- err
 	}()
 
-	_, err := respTransport.SecureInbound(context.TODO(), resp, "")
+	_, err := respTransport.SecureInbound(context.Background(), resp, "")
 	require.Error(t, err)
 
 	initErr := <-errChan
@@ -214,13 +214,13 @@ func TestPeerIDMismatchInboundFailsHandshake(t *testing.T) {
 	done := make(chan struct{})
 	go func() {
 		defer close(done)
-		conn, err := initTransport.SecureOutbound(context.TODO(), init, respTransport.localID)
+		conn, err := initTransport.SecureOutbound(context.Background(), init, respTransport.localID)
 		assert.NoError(t, err)
 		_, err = conn.Read([]byte{0})
 		assert.Error(t, err)
 	}()
 
-	_, err := respTransport.SecureInbound(context.TODO(), resp, "a-random-peer-id")
+	_, err := respTransport.SecureInbound(context.Background(), resp, "a-random-peer-id")
 	require.Error(t, err, "expected responder to fail with peer ID mismatch error")
 	<-done
 }
@@ -387,7 +387,7 @@ func TestPrologueMatches(t *testing.T) {
 		tpt, err := initTransport.
 			WithSessionOptions(Prologue(commonPrologue))
 		require.NoError(t, err)
-		conn, err := tpt.SecureOutbound(context.TODO(), initConn, respTransport.localID)
+		conn, err := tpt.SecureOutbound(context.Background(), initConn, respTransport.localID)
 		require.NoError(t, err)
 		defer conn.Close()
 	}()
@@ -395,7 +395,7 @@ func TestPrologueMatches(t *testing.T) {
 	tpt, err := respTransport.
 		WithSessionOptions(Prologue(commonPrologue))
 	require.NoError(t, err)
-	conn, err := tpt.SecureInbound(context.TODO(), respConn, "")
+	conn, err := tpt.SecureInbound(context.Background(), respConn, "")
 	require.NoError(t, err)
 	defer conn.Close()
 	<-done
@@ -415,14 +415,125 @@ func TestPrologueDoesNotMatchFailsHandshake(t *testing.T) {
 		tpt, err := initTransport.
 			WithSessionOptions(Prologue(initPrologue))
 		require.NoError(t, err)
-		_, err = tpt.SecureOutbound(context.TODO(), initConn, respTransport.localID)
+		_, err = tpt.SecureOutbound(context.Background(), initConn, respTransport.localID)
 		require.Error(t, err)
 	}()
 
 	tpt, err := respTransport.WithSessionOptions(Prologue(respPrologue))
 	require.NoError(t, err)
 
-	_, err = tpt.SecureInbound(context.TODO(), respConn, "")
+	_, err = tpt.SecureInbound(context.Background(), respConn, "")
 	require.Error(t, err)
 	<-done
 }
+
+type earlyDataHandler struct {
+	send     func(context.Context, net.Conn, peer.ID) []byte
+	received func(context.Context, net.Conn, []byte) error
+}
+
+func (e *earlyDataHandler) Send(ctx context.Context, conn net.Conn, id peer.ID) []byte {
+	if e.send == nil {
+		return nil
+	}
+	return e.send(ctx, conn, id)
+}
+
+func (e *earlyDataHandler) Received(ctx context.Context, conn net.Conn, data []byte) error {
+	if e.received == nil {
+		return nil
+	}
+	return e.received(ctx, conn, data)
+}
+
+func TestEarlyDataAccepted(t *testing.T) {
+	var receivedEarlyData []byte
+	serverEDH := &earlyDataHandler{
+		received: func(_ context.Context, _ net.Conn, data []byte) error {
+			receivedEarlyData = data
+			return nil
+		},
+	}
+	clientEDH := &earlyDataHandler{
+		send: func(ctx context.Context, conn net.Conn, id peer.ID) []byte { return []byte("foobar") },
+	}
+	initTransport, err := newTestTransport(t, crypto.Ed25519, 2048).WithSessionOptions(EarlyData(clientEDH))
+	require.NoError(t, err)
+	tpt := newTestTransport(t, crypto.Ed25519, 2048)
+	respTransport, err := tpt.WithSessionOptions(EarlyData(serverEDH))
+	require.NoError(t, err)
+
+	initConn, respConn := newConnPair(t)
+
+	errChan := make(chan error)
+	go func() {
+		_, err := respTransport.SecureInbound(context.Background(), initConn, "")
+		errChan <- err
+	}()
+
+	conn, err := initTransport.SecureOutbound(context.Background(), respConn, tpt.localID)
+	require.NoError(t, err)
+	defer conn.Close()
+
+	require.Equal(t, []byte("foobar"), receivedEarlyData)
+}
+
+func TestEarlyDataRejected(t *testing.T) {
+	serverEDH := &earlyDataHandler{
+		received: func(_ context.Context, _ net.Conn, data []byte) error { return errors.New("nope") },
+	}
+	clientEDH := &earlyDataHandler{
+		send: func(ctx context.Context, conn net.Conn, id peer.ID) []byte { return []byte("foobar") },
+	}
+	initTransport, err := newTestTransport(t, crypto.Ed25519, 2048).WithSessionOptions(EarlyData(clientEDH))
+	require.NoError(t, err)
+	tpt := newTestTransport(t, crypto.Ed25519, 2048)
+	respTransport, err := tpt.WithSessionOptions(EarlyData(serverEDH))
+	require.NoError(t, err)
+
+	initConn, respConn := newConnPair(t)
+
+	errChan := make(chan error)
+	go func() {
+		_, err := respTransport.SecureInbound(context.Background(), initConn, "")
+		errChan <- err
+	}()
+
+	_, err = initTransport.SecureOutbound(context.Background(), respConn, tpt.localID)
+	require.Error(t, err)
+
+	select {
+	case <-time.After(500 * time.Millisecond):
+		t.Fatal("timeout")
+	case err := <-errChan:
+		require.EqualError(t, err, "nope")
+	}
+}
+
+func TestEarlyDataRejectedWithNoHandler(t *testing.T) {
+	clientEDH := &earlyDataHandler{
+		send: func(ctx context.Context, conn net.Conn, id peer.ID) []byte { return []byte("foobar") },
+	}
+	initTransport, err := newTestTransport(t, crypto.Ed25519, 2048).WithSessionOptions(EarlyData(clientEDH))
+	require.NoError(t, err)
+	respTransport := newTestTransport(t, crypto.Ed25519, 2048)
+
+	initConn, respConn := newConnPair(t)
+
+	errChan := make(chan error)
+	go func() {
+		_, err := respTransport.SecureInbound(context.Background(), initConn, "")
+		errChan <- err
+	}()
+
+	_, err = initTransport.SecureOutbound(context.Background(), respConn, respTransport.localID)
+	require.Error(t, err)
+
+	select {
+	case <-time.After(500 * time.Millisecond):
+		t.Fatal("timeout")
+	case err := <-errChan:
+		require.Error(t, err)
+		require.Contains(t, err.Error(), "received unexpected early data")
+	}
+}