Merge pull request #13252 from yuzhiquan/fix-always-true-or-false

etcdserver: remove always true or false in if statement
diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
index 2487141..84a1a7b 100644
--- a/.github/workflows/e2e.yaml
+++ b/.github/workflows/e2e.yaml
@@ -21,7 +21,7 @@
         echo "${TARGET}"
         case "${TARGET}" in
           linux-amd64-e2e)
-            PASSES='build release e2e' MANUAL_VER=v3.4.7 CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log
+            PASSES='build release e2e' MANUAL_VER=v3.5.0 CPU='4' EXPECT_DEBUG='true' COVER='false' RACE='true' ./test.sh 2>&1 | tee test.log
             ! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 test.log
             ;;
           linux-386-e2e)
diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md
index 63926da..ded9393 100644
--- a/CHANGELOG-3.4.md
+++ b/CHANGELOG-3.4.md
@@ -972,7 +972,7 @@
   - Now [`(r *raft) Step` returns `raft.ErrProposalDropped`](https://github.com/etcd-io/etcd/pull/9137) if a proposal has been ignored.
   - e.g. a node is removed from cluster, or [`raftpb.MsgProp` arrives at current leader while there is an ongoing leadership transfer](https://github.com/etcd-io/etcd/issues/8975).
 - Improve [Raft `becomeLeader` and `stepLeader`](https://github.com/etcd-io/etcd/pull/9073) by keeping track of latest `pb.EntryConfChange` index.
-  - Previously record `pendingConf` boolean field scanning the entire tail of the log, which can delay hearbeat send.
+  - Previously record `pendingConf` boolean field scanning the entire tail of the log, which can delay heartbeat send.
 - Fix [missing learner nodes on `(n *node) ApplyConfChange`](https://github.com/etcd-io/etcd/pull/9116).
 - Add [`raft.Config.MaxUncommittedEntriesSize`](https://github.com/etcd-io/etcd/pull/10167) to limit the total size of the uncommitted entries in bytes.
   - Once exceeded, raft returns `raft.ErrProposalDropped` error.
diff --git a/CHANGELOG-3.5.md b/CHANGELOG-3.5.md
index 85db0c8..974c1bd 100644
--- a/CHANGELOG-3.5.md
+++ b/CHANGELOG-3.5.md
@@ -177,7 +177,7 @@
 - Add [`etcd --socket-reuse-address`](https://github.com/etcd-io/etcd/pull/12702) flag
   - Setting this flag enables `SO_REUSEADDR` which allows binding to an address in `TIME_WAIT` state, improving etcd restart time.
 - Reduce [around 30% memory allocation by logging range response size without marshal](https://github.com/etcd-io/etcd/pull/12871).
-- `ETCD_VERIFY="all"` environment triggers [additional verification of consistency](https://github.com/etcd-io/etcd/pull/) of etcd data-dir files.
+- `ETCD_VERIFY="all"` environment triggers [additional verification of consistency](https://github.com/etcd-io/etcd/pull/12901) of etcd data-dir files.
 - Add [`etcd --enable-log-rotation`](https://github.com/etcd-io/etcd/pull/12774) boolean flag which enables log rotation if true.
 - Add [`etcd --log-rotation-config-json`](https://github.com/etcd-io/etcd/pull/12774) flag which allows passthrough of JSON config to configure log rotation for a file output target.
 - Add experimental distributed tracing boolean flag [`--experimental-enable-distributed-tracing`](https://github.com/etcd-io/etcd/pull/12919) which enables tracing.
diff --git a/CHANGELOG-3.6.md b/CHANGELOG-3.6.md
index 36d0f7f..1094c26 100644
--- a/CHANGELOG-3.6.md
+++ b/CHANGELOG-3.6.md
@@ -15,9 +15,12 @@
 ### etcdutl v3
 
 - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13142).
+- Add `migrate` command for downgrading/upgrading etcd data dir files.
 
 ### Package `server`
 
 - Package `mvcc` was moved to `storage/mvcc`
 - Package `mvcc/backend` was moved to `storage/backend`
 - Package `mvcc/buckets` was moved to `storage/schema`
+- Package `wal` was moved to `storage/wal`
+- Package `datadir` was moved to `storage/datadir`
diff --git a/Makefile b/Makefile
index 9464b7f..3845d74 100644
--- a/Makefile
+++ b/Makefile
@@ -39,22 +39,6 @@
 	rm -rf ./tests/e2e/default.proxy
 	find ./ -name "127.0.0.1:*" -o -name "localhost:*" -o -name "*.log" -o -name "agent-*" -o -name "*.coverprofile" -o -name "testname-proxy-*" | $(XARGS)
 
-docker-clean:
-	docker images
-	docker image prune --force
-
-docker-start:
-	service docker restart
-
-docker-kill:
-	docker kill `docker ps -q` || true
-
-docker-remove:
-	docker rm --force `docker ps -a -q` || true
-	docker rmi --force `docker images -q` || true
-
-
-
 GO_VERSION ?= 1.16.3
 ETCD_VERSION ?= $(shell git rev-parse --short HEAD || echo "GitNotFound")
 
@@ -96,31 +80,6 @@
 	$(info GO_VERSION: $(GO_VERSION))
 	docker pull gcr.io/etcd-development/etcd-test:go$(GO_VERSION)
 
-
-
-# Example:
-#   make build-docker-test
-#   make compile-with-docker-test
-#   make compile-setup-gopath-with-docker-test
-
-compile-with-docker-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker run \
-	  --rm \
-	  --mount type=bind,source=`pwd`,destination=/go/src/go.etcd.io/etcd \
-	  gcr.io/etcd-development/etcd-test:go$(GO_VERSION) \
-	  /bin/bash -c "GO_BUILD_FLAGS=-v GOOS=linux GOARCH=amd64 ./build.sh && ./bin/etcd --version"
-
-compile-setup-gopath-with-docker-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker run \
-	  --rm \
-	  --mount type=bind,source=`pwd`,destination=/etcd \
-	  gcr.io/etcd-development/etcd-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && ETCD_SETUP_GOPATH=1 GO_BUILD_FLAGS=-v GOOS=linux GOARCH=amd64 ./build.sh && ./bin/etcd --version && rm -rf ./gopath"
-
-
-
 # Example:
 #
 # Local machine:
@@ -129,22 +88,9 @@
 #   TEST_OPTS="PASSES='build unit release integration_e2e functional'" make test
 #   TEST_OPTS="PASSES='build grpcproxy'" make test
 #
-# Example (test with docker):
-#   make pull-docker-test
-#   TEST_OPTS="PASSES='fmt'" make docker-test
-#   TEST_OPTS="VERBOSE=2 PASSES='unit'" make docker-test
-#
-# Travis CI (test with docker):
-#   TEST_OPTS="PASSES='fmt bom dep build unit'" make docker-test
-#
-# Semaphore CI (test with docker):
-#   TEST_OPTS="PASSES='build unit release integration_e2e functional'" make docker-test
-#   HOST_TMP_DIR=/tmp TEST_OPTS="PASSES='build unit release integration_e2e functional'" make docker-test
-#   TEST_OPTS="GOARCH=386 PASSES='build unit integration_e2e'" make docker-test
-#
-# grpc-proxy tests (test with docker):
-#   TEST_OPTS="PASSES='build grpcproxy'" make docker-test
-#   HOST_TMP_DIR=/tmp TEST_OPTS="PASSES='build grpcproxy'" make docker-test
+# grpc-proxy tests:
+#   TEST_OPTS="PASSES='build grpcproxy'" make test
+#   HOST_TMP_DIR=/tmp TEST_OPTS="PASSES='build grpcproxy'" make test
 
 .PHONY: test
 test:
@@ -191,9 +137,7 @@
 	! egrep "(--- FAIL:|FAIL:|DATA RACE|panic: test timed out|appears to have leaked)" -B50 -A10 docker-test-coverage-$(TEST_SUFFIX).log
 
 
-
 # Example:
-#   make compile-with-docker-test
 #   ETCD_VERSION=v3-test make build-docker-release-main
 #   ETCD_VERSION=v3-test make push-docker-release-main
 #   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
@@ -216,333 +160,3 @@
 push-docker-release-main:
 	$(info ETCD_VERSION: $(ETCD_VERSION))
 	docker push gcr.io/etcd-development/etcd:$(ETCD_VERSION)
-
-
-
-# Example:
-#   make build-docker-test
-#   make compile-with-docker-test
-#   make build-docker-static-ip-test
-#
-#   gcloud auth configure-docker
-#   make push-docker-static-ip-test
-#
-#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
-#   make pull-docker-static-ip-test
-#
-#   make docker-static-ip-test-certs-run
-#   make docker-static-ip-test-certs-metrics-proxy-run
-
-build-docker-static-ip-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' ./tests/docker-static-ip/Dockerfile > $(TMP_DOCKERFILE)
-	docker build \
-	  --network=host \
-	  --tag gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
-	  --file ./tests/docker-static-ip/Dockerfile \
-	  $(TMP_DOCKERFILE)
-
-push-docker-static-ip-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker push gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION)
-
-pull-docker-static-ip-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker pull gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION)
-
-docker-static-ip-test-certs-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-static-ip/certs,destination=/certs \
-	  gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
-
-docker-static-ip-test-certs-metrics-proxy-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-static-ip/certs-metrics-proxy,destination=/certs-metrics-proxy \
-	  gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-metrics-proxy/run.sh && rm -rf m*.etcd"
-
-
-
-# Example:
-#   make build-docker-test
-#   make compile-with-docker-test
-#   make build-docker-dns-test
-#
-#   gcloud auth configure-docker
-#   make push-docker-dns-test
-#
-#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
-#   make pull-docker-dns-test
-#
-#   make docker-dns-test-insecure-run
-#   make docker-dns-test-certs-run
-#   make docker-dns-test-certs-gateway-run
-#   make docker-dns-test-certs-wildcard-run
-#   make docker-dns-test-certs-common-name-auth-run
-#   make docker-dns-test-certs-common-name-multi-run
-#   make docker-dns-test-certs-san-dns-run
-
-build-docker-dns-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' ./tests/docker-dns/Dockerfile > $(TMP_DOCKERFILE)
-	docker build \
-	  --network=host \
-	  --tag gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  --file ./tests/docker-dns/Dockerfile \
-	  $(TMP_DOCKERFILE)
-
-	docker run \
-	  --rm \
-	  --dns 127.0.0.1 \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "/etc/init.d/bind9 start && cat /dev/null >/etc/hosts && dig etcd.local"
-
-push-docker-dns-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker push gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION)
-
-pull-docker-dns-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker pull gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION)
-
-docker-dns-test-insecure-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/insecure,destination=/insecure \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /insecure/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs,destination=/certs \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-gateway-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-gateway,destination=/certs-gateway \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-gateway/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-wildcard-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-wildcard,destination=/certs-wildcard \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-wildcard/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-common-name-auth-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-common-name-auth,destination=/certs-common-name-auth \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-common-name-auth/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-common-name-multi-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-common-name-multi,destination=/certs-common-name-multi \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-common-name-multi/run.sh && rm -rf m*.etcd"
-
-docker-dns-test-certs-san-dns-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-san-dns,destination=/certs-san-dns \
-	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-san-dns/run.sh && rm -rf m*.etcd"
-
-
-# Example:
-#   make build-docker-test
-#   make compile-with-docker-test
-#   make build-docker-dns-srv-test
-#   gcloud auth configure-docker
-#   make push-docker-dns-srv-test
-#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
-#   make pull-docker-dns-srv-test
-#   make docker-dns-srv-test-certs-run
-#   make docker-dns-srv-test-certs-gateway-run
-#   make docker-dns-srv-test-certs-wildcard-run
-
-build-docker-dns-srv-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' > $(TMP_DOCKERFILE)
-	docker build \
-	  --network=host \
-	  --tag gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
-	  --file ./tests/docker-dns-srv/Dockerfile \
-	  $(TMP_DOCKERFILE)
-
-	docker run \
-	  --rm \
-	  --dns 127.0.0.1 \
-	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
-	  /bin/bash -c "/etc/init.d/bind9 start && cat /dev/null >/etc/hosts && dig +noall +answer SRV _etcd-client-ssl._tcp.etcd.local && dig +noall +answer SRV _etcd-server-ssl._tcp.etcd.local && dig +noall +answer m1.etcd.local m2.etcd.local m3.etcd.local"
-
-push-docker-dns-srv-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker push gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION)
-
-pull-docker-dns-srv-test:
-	$(info GO_VERSION: $(GO_VERSION))
-	docker pull gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION)
-
-docker-dns-srv-test-certs-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs,destination=/certs \
-	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
-
-docker-dns-srv-test-certs-gateway-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs-gateway,destination=/certs-gateway \
-	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-gateway/run.sh && rm -rf m*.etcd"
-
-docker-dns-srv-test-certs-wildcard-run:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
-	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
-	docker run \
-	  --rm \
-	  --tty \
-	  --dns 127.0.0.1 \
-	  $(TMP_DIR_MOUNT_FLAG) \
-	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
-	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs-wildcard,destination=/certs-wildcard \
-	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
-	  /bin/bash -c "cd /etcd && /certs-wildcard/run.sh && rm -rf m*.etcd"
-
-
-
-# Example:
-#   make build-functional
-#   make build-docker-functional
-#   make push-docker-functional
-#   make pull-docker-functional
-
-build-functional:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info ETCD_VERSION: $(ETCD_VERSION))
-	./tests/functional/build
-	./bin/etcd-agent -help || true && \
-	  ./bin/etcd-proxy -help || true && \
-	  ./bin/etcd-runner --help || true && \
-	  ./bin/etcd-tester -help || true
-
-build-docker-functional:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info ETCD_VERSION: $(ETCD_VERSION))
-	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' > $(TMP_DOCKERFILE)
-	docker build \
-	  --network=host \
-	  --tag gcr.io/etcd-development/etcd-functional:go$(GO_VERSION) \
-	  --file ./tests/functional/Dockerfile \
-	  .
-	@mv ./tests/functional/Dockerfile.bak ./tests/functional/Dockerfile
-
-	docker run \
-	  --rm \
-	  gcr.io/etcd-development/etcd-functional:go$(GO_VERSION) \
-	  /bin/bash -c "./bin/etcd --version && \
-	   ./bin/etcd-failpoints --version && \
-	   ./bin/etcdctl version && \
-	   ./bin/etcdutl version && \
-	   ./bin/etcd-agent -help || true && \
-	   ./bin/etcd-proxy -help || true && \
-	   ./bin/etcd-runner --help || true && \
-	   ./bin/etcd-tester -help || true && \
-	   ./bin/benchmark --help || true"
-
-push-docker-functional:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info ETCD_VERSION: $(ETCD_VERSION))
-	docker push gcr.io/etcd-development/etcd-functional:go$(GO_VERSION)
-
-pull-docker-functional:
-	$(info GO_VERSION: $(GO_VERSION))
-	$(info ETCD_VERSION: $(ETCD_VERSION))
-	docker pull gcr.io/etcd-development/etcd-functional:go$(GO_VERSION)
diff --git a/api/etcdserverpb/raft_internal.pb.go b/api/etcdserverpb/raft_internal.pb.go
index b94a7bf..d59e658 100644
--- a/api/etcdserverpb/raft_internal.pb.go
+++ b/api/etcdserverpb/raft_internal.pb.go
@@ -12,6 +12,7 @@
 	_ "github.com/gogo/protobuf/gogoproto"
 	proto "github.com/golang/protobuf/proto"
 	membershippb "go.etcd.io/etcd/api/v3/membershippb"
+	_ "go.etcd.io/etcd/api/v3/versionpb"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -237,70 +238,73 @@
 func init() { proto.RegisterFile("raft_internal.proto", fileDescriptor_b4c9a9be0cfca103) }
 
 var fileDescriptor_b4c9a9be0cfca103 = []byte{
-	// 1003 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x96, 0xd9, 0x72, 0x1b, 0x45,
-	0x14, 0x86, 0x23, 0xc5, 0x71, 0xac, 0x96, 0xed, 0x38, 0x6d, 0x87, 0x34, 0x72, 0x95, 0x70, 0x1c,
-	0x12, 0xcc, 0x66, 0x53, 0xca, 0x03, 0x80, 0x90, 0x5c, 0x8e, 0xab, 0x42, 0x70, 0x4d, 0xcc, 0x52,
-	0xc5, 0xc5, 0xd0, 0x9a, 0x39, 0x96, 0x06, 0xcf, 0x46, 0x77, 0x4b, 0x31, 0xef, 0x11, 0x28, 0x1e,
-	0x83, 0xed, 0x21, 0x72, 0xc1, 0x62, 0xe0, 0x05, 0xc0, 0xdc, 0x70, 0x0f, 0xdc, 0x53, 0xbd, 0xcc,
-	0x26, 0xb5, 0x7c, 0xa7, 0xf9, 0xcf, 0x7f, 0xbe, 0x73, 0xba, 0xe7, 0xf4, 0xa8, 0xd1, 0x3a, 0xa3,
-	0x27, 0xc2, 0x0d, 0x62, 0x01, 0x2c, 0xa6, 0xe1, 0x6e, 0xca, 0x12, 0x91, 0xe0, 0x65, 0x10, 0x9e,
-	0xcf, 0x81, 0x4d, 0x80, 0xa5, 0x83, 0xd6, 0xc6, 0x30, 0x19, 0x26, 0x2a, 0xb0, 0x27, 0x7f, 0x69,
-	0x4f, 0x6b, 0xad, 0xf0, 0x18, 0xa5, 0xc1, 0x52, 0xcf, 0xfc, 0xbc, 0x2f, 0x83, 0x7b, 0x34, 0x0d,
-	0xf6, 0x22, 0x88, 0x06, 0xc0, 0xf8, 0x28, 0x48, 0xd3, 0x41, 0xe9, 0x41, 0xfb, 0xb6, 0x3f, 0x45,
-	0x2b, 0x0e, 0x7c, 0x3e, 0x06, 0x2e, 0x1e, 0x02, 0xf5, 0x81, 0xe1, 0x55, 0x54, 0x3f, 0xec, 0x93,
-	0xda, 0x56, 0x6d, 0x67, 0xc1, 0xa9, 0x1f, 0xf6, 0x71, 0x0b, 0x2d, 0x8d, 0xb9, 0x6c, 0x2d, 0x02,
-	0x52, 0xdf, 0xaa, 0xed, 0x34, 0x9c, 0xfc, 0x19, 0xdf, 0x45, 0x2b, 0x74, 0x2c, 0x46, 0x2e, 0x83,
-	0x49, 0xc0, 0x83, 0x24, 0x26, 0x57, 0x55, 0xda, 0xb2, 0x14, 0x1d, 0xa3, 0x6d, 0x3f, 0xc3, 0x68,
-	0xfd, 0xd0, 0xac, 0xce, 0xa1, 0x27, 0xc2, 0x94, 0xc3, 0x0f, 0xd0, 0xe2, 0x48, 0x95, 0x24, 0xfe,
-	0x56, 0x6d, 0xa7, 0xd9, 0xd9, 0xdc, 0x2d, 0xaf, 0x79, 0xb7, 0xd2, 0x95, 0x63, 0xac, 0x33, 0xdd,
-	0xdd, 0x43, 0xf5, 0x49, 0x47, 0xf5, 0xd5, 0xec, 0xdc, 0xb2, 0x02, 0x9c, 0xfa, 0xa4, 0x83, 0xdf,
-	0x42, 0xd7, 0x18, 0x8d, 0x87, 0xa0, 0x1a, 0x6c, 0x76, 0x5a, 0x53, 0x4e, 0x19, 0xca, 0xec, 0xda,
-	0x88, 0x5f, 0x43, 0x57, 0xd3, 0xb1, 0x20, 0x0b, 0xca, 0x4f, 0xaa, 0xfe, 0xa3, 0x71, 0xb6, 0x08,
-	0x47, 0x9a, 0x70, 0x0f, 0x2d, 0xfb, 0x10, 0x82, 0x00, 0x57, 0x17, 0xb9, 0xa6, 0x92, 0xb6, 0xaa,
-	0x49, 0x7d, 0xe5, 0xa8, 0x94, 0x6a, 0xfa, 0x85, 0x26, 0x0b, 0x8a, 0xb3, 0x98, 0x2c, 0xda, 0x0a,
-	0x1e, 0x9f, 0xc5, 0x79, 0x41, 0x71, 0x16, 0xe3, 0xb7, 0x11, 0xf2, 0x92, 0x28, 0xa5, 0x9e, 0x90,
-	0x9b, 0x7e, 0x5d, 0xa5, 0xbc, 0x54, 0x4d, 0xe9, 0xe5, 0xf1, 0x2c, 0xb3, 0x94, 0x82, 0xdf, 0x41,
-	0xcd, 0x10, 0x28, 0x07, 0x77, 0xc8, 0x68, 0x2c, 0xc8, 0x92, 0x8d, 0xf0, 0x48, 0x1a, 0x0e, 0x64,
-	0x3c, 0x27, 0x84, 0xb9, 0x24, 0xd7, 0xac, 0x09, 0x0c, 0x26, 0xc9, 0x29, 0x90, 0x86, 0x6d, 0xcd,
-	0x0a, 0xe1, 0x28, 0x43, 0xbe, 0xe6, 0xb0, 0xd0, 0xe4, 0x6b, 0xa1, 0x21, 0x65, 0x11, 0x41, 0xb6,
-	0xd7, 0xd2, 0x95, 0xa1, 0xfc, 0xb5, 0x28, 0x23, 0x7e, 0x1f, 0xad, 0xe9, 0xb2, 0xde, 0x08, 0xbc,
-	0xd3, 0x34, 0x09, 0x62, 0x41, 0x9a, 0x2a, 0xf9, 0x65, 0x4b, 0xe9, 0x5e, 0x6e, 0xca, 0x30, 0x37,
-	0xc2, 0xaa, 0x8e, 0xbb, 0xa8, 0xa9, 0x46, 0x18, 0x62, 0x3a, 0x08, 0x81, 0xfc, 0x6d, 0xdd, 0xcc,
-	0xee, 0x58, 0x8c, 0xf6, 0x95, 0x21, 0xdf, 0x0a, 0x9a, 0x4b, 0xb8, 0x8f, 0xd4, 0xc0, 0xbb, 0x7e,
-	0xc0, 0x15, 0xe3, 0x9f, 0xeb, 0xb6, 0xbd, 0x90, 0x8c, 0xbe, 0x76, 0xe4, 0x7b, 0x41, 0x0b, 0x2d,
-	0x6f, 0x84, 0x0b, 0x2a, 0xc6, 0x9c, 0xfc, 0x37, 0xb7, 0x91, 0x27, 0xca, 0x50, 0x69, 0x44, 0x4b,
-	0xf8, 0xb1, 0x6e, 0x04, 0x62, 0x11, 0x78, 0x54, 0x00, 0xf9, 0x57, 0x33, 0x5e, 0xad, 0x32, 0xb2,
-	0xb3, 0xd8, 0x2d, 0x59, 0x33, 0x5a, 0x25, 0x1f, 0xef, 0x9b, 0xe3, 0x2d, 0xcf, 0xbb, 0x4b, 0x7d,
-	0x9f, 0xfc, 0xb8, 0x34, 0x6f, 0x65, 0x1f, 0x70, 0x60, 0x5d, 0xdf, 0xaf, 0xac, 0xcc, 0x68, 0xf8,
-	0x31, 0x5a, 0x2b, 0x30, 0x7a, 0xe4, 0xc9, 0x4f, 0x9a, 0x74, 0xd7, 0x4e, 0x32, 0x67, 0xc5, 0xc0,
-	0x56, 0x69, 0x45, 0xae, 0xb6, 0x35, 0x04, 0x41, 0x7e, 0xbe, 0xb4, 0xad, 0x03, 0x10, 0x33, 0x6d,
-	0x1d, 0x80, 0xc0, 0x43, 0xf4, 0x62, 0x81, 0xf1, 0x46, 0xf2, 0x10, 0xba, 0x29, 0xe5, 0xfc, 0x69,
-	0xc2, 0x7c, 0xf2, 0x8b, 0x46, 0xbe, 0x6e, 0x47, 0xf6, 0x94, 0xfb, 0xc8, 0x98, 0x33, 0xfa, 0x0b,
-	0xd4, 0x1a, 0xc6, 0x1f, 0xa3, 0x8d, 0x52, 0xbf, 0xf2, 0xf4, 0xb8, 0x2c, 0x09, 0x81, 0x9c, 0xeb,
-	0x1a, 0xf7, 0xe7, 0xb4, 0xad, 0x4e, 0x5e, 0x52, 0x4c, 0xcb, 0x4d, 0x3a, 0x1d, 0xc1, 0x9f, 0xa0,
-	0x5b, 0x05, 0x59, 0x1f, 0x44, 0x8d, 0xfe, 0x55, 0xa3, 0x5f, 0xb1, 0xa3, 0xcd, 0x89, 0x2c, 0xb1,
-	0x31, 0x9d, 0x09, 0xe1, 0x87, 0x68, 0xb5, 0x80, 0x87, 0x01, 0x17, 0xe4, 0x37, 0x4d, 0xbd, 0x63,
-	0xa7, 0x3e, 0x0a, 0xb8, 0xa8, 0xcc, 0x51, 0x26, 0xe6, 0x24, 0xd9, 0x9a, 0x26, 0xfd, 0x3e, 0x97,
-	0x24, 0x4b, 0xcf, 0x90, 0x32, 0x31, 0x7f, 0xf5, 0x8a, 0x24, 0x27, 0xf2, 0x9b, 0xc6, 0xbc, 0x57,
-	0x2f, 0x73, 0xa6, 0x27, 0xd2, 0x68, 0xf9, 0x44, 0x2a, 0x8c, 0x99, 0xc8, 0x6f, 0x1b, 0xf3, 0x26,
-	0x52, 0x66, 0x59, 0x26, 0xb2, 0x90, 0xab, 0x6d, 0xc9, 0x89, 0xfc, 0xee, 0xd2, 0xb6, 0xa6, 0x27,
-	0xd2, 0x68, 0xf8, 0x33, 0xd4, 0x2a, 0x61, 0xd4, 0xa0, 0xa4, 0xc0, 0xa2, 0x80, 0xab, 0xff, 0xd6,
-	0xef, 0x35, 0xf3, 0x8d, 0x39, 0x4c, 0x69, 0x3f, 0xca, 0xdd, 0x19, 0xff, 0x36, 0xb5, 0xc7, 0x71,
-	0x84, 0x36, 0x8b, 0x5a, 0x66, 0x74, 0x4a, 0xc5, 0x7e, 0xd0, 0xc5, 0xde, 0xb4, 0x17, 0xd3, 0x53,
-	0x32, 0x5b, 0x8d, 0xd0, 0x39, 0x06, 0xfc, 0x11, 0x5a, 0xf7, 0xc2, 0x31, 0x17, 0xc0, 0xdc, 0x09,
-	0x30, 0x29, 0xb9, 0x1c, 0x04, 0x79, 0x86, 0xcc, 0x11, 0x28, 0x5f, 0x52, 0x76, 0x7b, 0xda, 0xf9,
-	0xa1, 0x36, 0x3e, 0x29, 0x76, 0xeb, 0xa6, 0x37, 0x1d, 0xc1, 0x14, 0xdd, 0xce, 0xc0, 0x9a, 0xe1,
-	0x52, 0x21, 0x98, 0x82, 0x7f, 0x89, 0xcc, 0xe7, 0xcf, 0x06, 0x7f, 0x4f, 0x69, 0x5d, 0x21, 0x58,
-	0x89, 0xbf, 0xe1, 0x59, 0x82, 0xf8, 0x18, 0x61, 0x3f, 0x79, 0x1a, 0x0f, 0x19, 0xf5, 0xc1, 0x0d,
-	0xe2, 0x93, 0x44, 0xd1, 0xbf, 0xd2, 0xf4, 0x7b, 0x55, 0x7a, 0x3f, 0x33, 0x1e, 0xc6, 0x27, 0x49,
-	0x89, 0xbc, 0xe6, 0x4f, 0x05, 0xb6, 0x6f, 0xa0, 0x95, 0xfd, 0x28, 0x15, 0x5f, 0x38, 0xc0, 0xd3,
-	0x24, 0xe6, 0xb0, 0x9d, 0xa2, 0xcd, 0x4b, 0x3e, 0xcd, 0x18, 0xa3, 0x05, 0x75, 0x07, 0xab, 0xa9,
-	0x3b, 0x98, 0xfa, 0x2d, 0xef, 0x66, 0xf9, 0x17, 0xcb, 0xdc, 0xcd, 0xb2, 0x67, 0x7c, 0x07, 0x2d,
-	0xf3, 0x20, 0x4a, 0x43, 0x70, 0x45, 0x72, 0x0a, 0xfa, 0x6a, 0xd6, 0x70, 0x9a, 0x5a, 0x3b, 0x96,
-	0xd2, 0xbb, 0x1b, 0xcf, 0xff, 0x6c, 0x5f, 0x79, 0x7e, 0xd1, 0xae, 0x9d, 0x5f, 0xb4, 0x6b, 0x7f,
-	0x5c, 0xb4, 0x6b, 0x5f, 0xff, 0xd5, 0xbe, 0x32, 0x58, 0x54, 0x17, 0xc3, 0x07, 0xff, 0x07, 0x00,
-	0x00, 0xff, 0xff, 0x94, 0x6f, 0x64, 0x0a, 0x98, 0x0a, 0x00, 0x00,
+	// 1054 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x56, 0x5d, 0x6f, 0x1b, 0x45,
+	0x14, 0xad, 0xd3, 0x34, 0x89, 0xc7, 0x49, 0x9a, 0x4e, 0x52, 0x3a, 0x38, 0x92, 0x71, 0x03, 0x2d,
+	0x01, 0x8a, 0x53, 0x1c, 0x78, 0xe1, 0x05, 0x5c, 0x3b, 0x4a, 0x83, 0x4a, 0x15, 0x6d, 0x0b, 0xaa,
+	0x84, 0xd0, 0x32, 0xde, 0xbd, 0xb1, 0xb7, 0x59, 0xef, 0x2e, 0x33, 0x63, 0x37, 0x7d, 0xe5, 0x91,
+	0x67, 0x40, 0xfc, 0x0c, 0x3e, 0xff, 0x43, 0x85, 0xf8, 0x28, 0xf0, 0x07, 0x20, 0xbc, 0xf0, 0x0e,
+	0xbc, 0xa3, 0xf9, 0xd8, 0x5d, 0xaf, 0x3d, 0xce, 0xdb, 0xfa, 0xde, 0x73, 0xcf, 0x39, 0x33, 0x73,
+	0xef, 0x78, 0xd0, 0x3a, 0xa3, 0x47, 0xc2, 0x0d, 0x22, 0x01, 0x2c, 0xa2, 0x61, 0x23, 0x61, 0xb1,
+	0x88, 0xf1, 0x32, 0x08, 0xcf, 0xe7, 0xc0, 0x46, 0xc0, 0x92, 0x6e, 0x75, 0xa3, 0x17, 0xf7, 0x62,
+	0x95, 0xd8, 0x91, 0x5f, 0x1a, 0x53, 0x5d, 0xcb, 0x31, 0x26, 0x52, 0x66, 0x89, 0x67, 0x3e, 0xeb,
+	0x32, 0xb9, 0x43, 0x93, 0x60, 0x67, 0x04, 0x8c, 0x07, 0x71, 0x94, 0x74, 0xd3, 0x2f, 0x83, 0xb8,
+	0x9e, 0x21, 0x06, 0x30, 0xe8, 0x02, 0xe3, 0xfd, 0x20, 0x49, 0xba, 0x63, 0x3f, 0x34, 0x6e, 0x8b,
+	0xa1, 0x15, 0x07, 0x3e, 0x1e, 0x02, 0x17, 0xb7, 0x81, 0xfa, 0xc0, 0xf0, 0x2a, 0x9a, 0x3b, 0xe8,
+	0x90, 0x52, 0xbd, 0xb4, 0x3d, 0xef, 0xcc, 0x1d, 0x74, 0x70, 0x15, 0x2d, 0x0d, 0xb9, 0x34, 0x3f,
+	0x00, 0x32, 0x57, 0x2f, 0x6d, 0x97, 0x9d, 0xec, 0x37, 0xbe, 0x81, 0x56, 0xe8, 0x50, 0xf4, 0x5d,
+	0x06, 0xa3, 0x40, 0x6a, 0x93, 0xf3, 0xb2, 0xec, 0xd6, 0xe2, 0xa7, 0xdf, 0x93, 0xf3, 0xbb, 0x8d,
+	0xd7, 0x9c, 0x65, 0x99, 0x75, 0x4c, 0xf2, 0xcd, 0xc5, 0x4f, 0x54, 0xf8, 0xe6, 0xd6, 0x0f, 0x18,
+	0xad, 0x1f, 0x98, 0x1d, 0x71, 0xe8, 0x91, 0x30, 0x06, 0xf0, 0x2e, 0x5a, 0xe8, 0x2b, 0x13, 0xc4,
+	0xaf, 0x97, 0xb6, 0x2b, 0xcd, 0xcd, 0xc6, 0xf8, 0x3e, 0x35, 0x0a, 0x3e, 0x1d, 0x03, 0x9d, 0xf2,
+	0x7b, 0x0d, 0xcd, 0x8d, 0x9a, 0xca, 0x69, 0xa5, 0x79, 0xd9, 0x4a, 0xe0, 0xcc, 0x8d, 0x9a, 0xf8,
+	0x26, 0xba, 0xc0, 0x68, 0xd4, 0x03, 0x65, 0xb9, 0xd2, 0xac, 0x4e, 0x20, 0x65, 0x2a, 0x85, 0x6b,
+	0x20, 0x7e, 0x19, 0x9d, 0x4f, 0x86, 0x82, 0xcc, 0x2b, 0x3c, 0x29, 0xe2, 0x0f, 0x87, 0xe9, 0x22,
+	0x1c, 0x09, 0xc2, 0x6d, 0xb4, 0xec, 0x43, 0x08, 0x02, 0x5c, 0x2d, 0x72, 0x41, 0x15, 0xd5, 0x8b,
+	0x45, 0x1d, 0x85, 0x28, 0x48, 0x55, 0xfc, 0x3c, 0x26, 0x05, 0xc5, 0x49, 0x44, 0x16, 0x6c, 0x82,
+	0xf7, 0x4f, 0xa2, 0x4c, 0x50, 0x9c, 0x44, 0xf8, 0x2d, 0x84, 0xbc, 0x78, 0x90, 0x50, 0x4f, 0xc8,
+	0x63, 0x58, 0x54, 0x25, 0xcf, 0x15, 0x4b, 0xda, 0x59, 0x3e, 0xad, 0x1c, 0x2b, 0xc1, 0x6f, 0xa3,
+	0x4a, 0x08, 0x94, 0x83, 0xdb, 0x63, 0x34, 0x12, 0x64, 0xc9, 0xc6, 0x70, 0x47, 0x02, 0xf6, 0x65,
+	0x3e, 0x63, 0x08, 0xb3, 0x90, 0x5c, 0xb3, 0x66, 0x60, 0x30, 0x8a, 0x8f, 0x81, 0x94, 0x6d, 0x6b,
+	0x56, 0x14, 0x8e, 0x02, 0x64, 0x6b, 0x0e, 0xf3, 0x98, 0x3c, 0x16, 0x1a, 0x52, 0x36, 0x20, 0xc8,
+	0x76, 0x2c, 0x2d, 0x99, 0xca, 0x8e, 0x45, 0x01, 0xf1, 0x03, 0xb4, 0xa6, 0x65, 0xbd, 0x3e, 0x78,
+	0xc7, 0x49, 0x1c, 0x44, 0x82, 0x54, 0x54, 0xf1, 0x0b, 0x16, 0xe9, 0x76, 0x06, 0x32, 0x34, 0x69,
+	0xb3, 0xbe, 0xee, 0x5c, 0x0c, 0x8b, 0x00, 0xdc, 0x42, 0x15, 0xd5, 0xdd, 0x10, 0xd1, 0x6e, 0x08,
+	0xe4, 0x6f, 0xeb, 0xae, 0xb6, 0x86, 0xa2, 0xbf, 0xa7, 0x00, 0xd9, 0x9e, 0xd0, 0x2c, 0x84, 0x3b,
+	0x48, 0x8d, 0x80, 0xeb, 0x07, 0x5c, 0x71, 0xfc, 0xb3, 0x68, 0xdb, 0x14, 0xc9, 0xd1, 0xd1, 0x88,
+	0x6c, 0x53, 0x68, 0x1e, 0xc3, 0xef, 0x18, 0x23, 0x5c, 0x50, 0x31, 0xe4, 0xe4, 0xbf, 0x99, 0x46,
+	0xee, 0x29, 0xc0, 0xc4, 0xca, 0xde, 0xd0, 0x8e, 0x74, 0x0e, 0xdf, 0xd5, 0x8e, 0x20, 0x12, 0x81,
+	0x47, 0x05, 0x90, 0x7f, 0x35, 0xd9, 0x4b, 0x45, 0xb2, 0x74, 0x3a, 0x5b, 0x63, 0xd0, 0xd4, 0x5a,
+	0xa1, 0x1e, 0xef, 0x99, 0x2b, 0x40, 0xde, 0x09, 0x2e, 0xf5, 0x7d, 0xf2, 0xe3, 0xd2, 0xac, 0x25,
+	0xbe, 0xc7, 0x81, 0xb5, 0x7c, 0xbf, 0xb0, 0x44, 0x13, 0xc3, 0x77, 0xd1, 0x5a, 0x4e, 0xa3, 0x87,
+	0x80, 0xfc, 0xa4, 0x99, 0x9e, 0xb7, 0x33, 0x99, 0xe9, 0x31, 0x64, 0xab, 0xb4, 0x10, 0x2e, 0xda,
+	0xea, 0x81, 0x20, 0x3f, 0x9f, 0x69, 0x6b, 0x1f, 0xc4, 0x94, 0xad, 0x7d, 0x10, 0xb8, 0x87, 0x9e,
+	0xcd, 0x69, 0xbc, 0xbe, 0x1c, 0x4b, 0x37, 0xa1, 0x9c, 0x3f, 0x8a, 0x99, 0x4f, 0x7e, 0xd1, 0x94,
+	0xaf, 0xd8, 0x29, 0xdb, 0x0a, 0x7d, 0x68, 0xc0, 0x29, 0xfb, 0x33, 0xd4, 0x9a, 0xc6, 0x0f, 0xd0,
+	0xc6, 0x98, 0x5f, 0x39, 0x4f, 0x2e, 0x8b, 0x43, 0x20, 0x4f, 0xb5, 0xc6, 0xf5, 0x19, 0xb6, 0xd5,
+	0x2c, 0xc6, 0x79, 0xdb, 0x5c, 0xa2, 0x93, 0x19, 0xfc, 0x01, 0xba, 0x9c, 0x33, 0xeb, 0xd1, 0xd4,
+	0xd4, 0xbf, 0x6a, 0xea, 0x17, 0xed, 0xd4, 0x66, 0x46, 0xc7, 0xb8, 0x31, 0x9d, 0x4a, 0xe1, 0xdb,
+	0x68, 0x35, 0x27, 0x0f, 0x03, 0x2e, 0xc8, 0x6f, 0x9a, 0xf5, 0xaa, 0x9d, 0xf5, 0x4e, 0xc0, 0x45,
+	0xa1, 0x8f, 0xd2, 0x60, 0xc6, 0x24, 0xad, 0x69, 0xa6, 0xdf, 0x67, 0x32, 0x49, 0xe9, 0x29, 0xa6,
+	0x34, 0x98, 0x1d, 0xbd, 0x62, 0x92, 0x1d, 0xf9, 0x55, 0x79, 0xd6, 0xd1, 0xcb, 0x9a, 0xc9, 0x8e,
+	0x34, 0xb1, 0xac, 0x23, 0x15, 0x8d, 0xe9, 0xc8, 0xaf, 0xcb, 0xb3, 0x3a, 0x52, 0x56, 0x59, 0x3a,
+	0x32, 0x0f, 0x17, 0x6d, 0xc9, 0x8e, 0xfc, 0xe6, 0x4c, 0x5b, 0x93, 0x1d, 0x69, 0x62, 0xf8, 0x21,
+	0xaa, 0x8e, 0xd1, 0xa8, 0x46, 0x49, 0x80, 0x0d, 0x02, 0xae, 0xfe, 0x7f, 0xbf, 0xd5, 0x9c, 0x37,
+	0x66, 0x70, 0x4a, 0xf8, 0x61, 0x86, 0x4e, 0xf9, 0xaf, 0x50, 0x7b, 0x1e, 0x0f, 0xd0, 0x66, 0xae,
+	0x65, 0x5a, 0x67, 0x4c, 0xec, 0x3b, 0x2d, 0xf6, 0xaa, 0x5d, 0x4c, 0x77, 0xc9, 0xb4, 0x1a, 0xa1,
+	0x33, 0x00, 0xf8, 0x23, 0xb4, 0xee, 0x85, 0x43, 0x2e, 0x80, 0xb9, 0xe6, 0x2d, 0xe3, 0x72, 0x10,
+	0xe4, 0x33, 0x64, 0x46, 0x60, 0xfc, 0x21, 0xd3, 0x68, 0x6b, 0xe4, 0xfb, 0x1a, 0x78, 0x0f, 0xc4,
+	0xd4, 0xad, 0x77, 0xc9, 0x9b, 0x84, 0xe0, 0x87, 0xe8, 0x4a, 0xaa, 0xa0, 0xc9, 0x5c, 0x2a, 0x04,
+	0x53, 0x2a, 0x9f, 0x23, 0x73, 0x0f, 0xda, 0x54, 0xde, 0x55, 0xb1, 0x96, 0x10, 0xcc, 0x26, 0xb4,
+	0xe1, 0x59, 0x50, 0xf8, 0x43, 0x84, 0xfd, 0xf8, 0x51, 0xd4, 0x63, 0xd4, 0x07, 0x37, 0x88, 0x8e,
+	0x62, 0x25, 0xf3, 0x85, 0x96, 0xb9, 0x56, 0x94, 0xe9, 0xa4, 0xc0, 0x83, 0xe8, 0x28, 0xb6, 0x49,
+	0xac, 0xf9, 0x13, 0x88, 0xfc, 0x31, 0x75, 0x11, 0xad, 0xec, 0x0d, 0x12, 0xf1, 0xd8, 0x01, 0x9e,
+	0xc4, 0x11, 0x87, 0xad, 0xc7, 0x68, 0xf3, 0x8c, 0xeb, 0x1b, 0x63, 0x34, 0xaf, 0xde, 0x72, 0x25,
+	0xf5, 0x96, 0x53, 0xdf, 0xf2, 0x8d, 0x97, 0xdd, 0x6a, 0xe6, 0x8d, 0x97, 0xfe, 0xc6, 0x57, 0xd1,
+	0x32, 0x0f, 0x06, 0x49, 0x08, 0xae, 0x88, 0x8f, 0x41, 0x3f, 0xf1, 0xca, 0x4e, 0x45, 0xc7, 0xee,
+	0xcb, 0x50, 0xe6, 0xe5, 0xd6, 0xc6, 0x93, 0x3f, 0x6b, 0xe7, 0x9e, 0x9c, 0xd6, 0x4a, 0x4f, 0x4f,
+	0x6b, 0xa5, 0x3f, 0x4e, 0x6b, 0xa5, 0x2f, 0xff, 0xaa, 0x9d, 0xeb, 0x2e, 0xa8, 0x97, 0xe6, 0xee,
+	0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x30, 0x36, 0x53, 0xc6, 0x0b, 0x0b, 0x00, 0x00,
 }
 
 func (m *RequestHeader) Marshal() (dAtA []byte, err error) {
diff --git a/api/etcdserverpb/raft_internal.proto b/api/etcdserverpb/raft_internal.proto
index 68926e5..f1036b9 100644
--- a/api/etcdserverpb/raft_internal.proto
+++ b/api/etcdserverpb/raft_internal.proto
@@ -4,6 +4,7 @@
 import "gogoproto/gogo.proto";
 import "etcdserver.proto";
 import "rpc.proto";
+import "etcd/api/versionpb/version.proto";
 import "etcd/api/membershippb/membership.proto";
 
 option (gogoproto.marshaler_all) = true;
@@ -12,16 +13,20 @@
 option (gogoproto.goproto_getters_all) = false;
 
 message RequestHeader {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   uint64 ID = 1;
   // username is a username that is associated with an auth token of gRPC connection
   string username = 2;
   // auth_revision is a revision number of auth.authStore. It is not related to mvcc
-  uint64 auth_revision = 3;
+  uint64 auth_revision = 3 [(versionpb.etcd_version_field) = "3.1"];
 }
 
 // An InternalRaftRequest is the union of all requests which can be
 // sent via raft.
 message InternalRaftRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   RequestHeader header = 100;
   uint64 ID = 1;
 
@@ -38,11 +43,11 @@
 
   AlarmRequest alarm = 10;
 
-  LeaseCheckpointRequest lease_checkpoint = 11;
+  LeaseCheckpointRequest lease_checkpoint = 11 [(versionpb.etcd_version_field) = "3.4"];
 
   AuthEnableRequest auth_enable = 1000;
   AuthDisableRequest auth_disable = 1011;
-  AuthStatusRequest auth_status = 1013;
+  AuthStatusRequest auth_status = 1013 [(versionpb.etcd_version_field) = "3.5"];
 
   InternalAuthenticateRequest authenticate = 1012;
 
@@ -61,9 +66,9 @@
   AuthRoleGrantPermissionRequest auth_role_grant_permission = 1203;
   AuthRoleRevokePermissionRequest auth_role_revoke_permission = 1204;
 
-  membershippb.ClusterVersionSetRequest cluster_version_set = 1300;
-  membershippb.ClusterMemberAttrSetRequest cluster_member_attr_set = 1301;
-  membershippb.DowngradeInfoSetRequest  downgrade_info_set = 1302;
+  membershippb.ClusterVersionSetRequest cluster_version_set = 1300 [(versionpb.etcd_version_field) = "3.5"];
+  membershippb.ClusterMemberAttrSetRequest cluster_member_attr_set = 1301 [(versionpb.etcd_version_field) = "3.5"];
+  membershippb.DowngradeInfoSetRequest  downgrade_info_set = 1302 [(versionpb.etcd_version_field) = "3.5"];
 }
 
 message EmptyResponse {
@@ -73,6 +78,7 @@
 // InternalAuthenticateRequest has a member that is filled by etcdserver and shouldn't be user-facing.
 // For avoiding misusage the field, we have an internal version of AuthenticateRequest.
 message InternalAuthenticateRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
   string name = 1;
   string password = 2;
 
diff --git a/api/etcdserverpb/rpc.pb.go b/api/etcdserverpb/rpc.pb.go
index 8b32ec1..0e22aed 100644
--- a/api/etcdserverpb/rpc.pb.go
+++ b/api/etcdserverpb/rpc.pb.go
@@ -14,6 +14,7 @@
 	proto "github.com/golang/protobuf/proto"
 	authpb "go.etcd.io/etcd/api/v3/authpb"
 	mvccpb "go.etcd.io/etcd/api/v3/mvccpb"
+	_ "go.etcd.io/etcd/api/v3/versionpb"
 	_ "google.golang.org/genproto/googleapis/api/annotations"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
@@ -276,7 +277,7 @@
 	MemberId uint64 `protobuf:"varint,2,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"`
 	// revision is the key-value store revision when the request was applied.
 	// For watch progress responses, the header.revision indicates progress. All future events
-	// recieved in this stream are guaranteed to have a higher revision number than the
+	// received in this stream are guaranteed to have a higher revision number than the
 	// header.revision number.
 	Revision int64 `protobuf:"varint,3,opt,name=revision,proto3" json:"revision,omitempty"`
 	// raft_term is the raft term when the request was applied.
@@ -6165,265 +6166,282 @@
 func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) }
 
 var fileDescriptor_77a6da22d6a3feb1 = []byte{
-	// 4115 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0x5b, 0x73, 0x1b, 0xc9,
-	0x75, 0xe6, 0x00, 0x24, 0x40, 0x1c, 0x5c, 0x08, 0x36, 0x2f, 0x82, 0xb0, 0x12, 0xc5, 0x6d, 0xad,
-	0xb4, 0x5c, 0x69, 0x97, 0x5c, 0xd3, 0x76, 0xb6, 0x4a, 0x49, 0x1c, 0x43, 0x24, 0x56, 0xe2, 0x92,
-	0x22, 0xb9, 0x43, 0x48, 0x7b, 0x29, 0x57, 0x58, 0x43, 0xa0, 0x45, 0x4e, 0x08, 0xcc, 0xc0, 0x33,
-	0x03, 0x88, 0xdc, 0x5c, 0x9c, 0x72, 0x39, 0xae, 0xe4, 0xd5, 0xae, 0x4a, 0x25, 0x0f, 0x49, 0x1e,
-	0x52, 0x29, 0x97, 0x1f, 0xfc, 0x9c, 0xbf, 0x90, 0xa7, 0x5c, 0x2a, 0x7f, 0x20, 0xb5, 0xf1, 0x4b,
-	0xf2, 0x23, 0x52, 0xa9, 0xbe, 0xcd, 0x74, 0xcf, 0x85, 0x94, 0x8d, 0xdd, 0x7d, 0x11, 0xd1, 0xa7,
-	0x4f, 0x9f, 0xef, 0xf4, 0xe9, 0xee, 0x73, 0x4e, 0x9f, 0x1e, 0x41, 0xc9, 0x1b, 0x76, 0xd7, 0x87,
-	0x9e, 0x1b, 0xb8, 0xa8, 0x42, 0x82, 0x6e, 0xcf, 0x27, 0xde, 0x98, 0x78, 0xc3, 0x93, 0xe6, 0xe2,
-	0xa9, 0x7b, 0xea, 0xb2, 0x8e, 0x0d, 0xfa, 0x8b, 0xf3, 0x34, 0x1b, 0x94, 0x67, 0xc3, 0x1a, 0xda,
-	0x1b, 0x83, 0x71, 0xb7, 0x3b, 0x3c, 0xd9, 0x38, 0x1f, 0x8b, 0x9e, 0x66, 0xd8, 0x63, 0x8d, 0x82,
-	0xb3, 0xe1, 0x09, 0xfb, 0x23, 0xfa, 0x6e, 0x9d, 0xba, 0xee, 0x69, 0x9f, 0xf0, 0x5e, 0xc7, 0x71,
-	0x03, 0x2b, 0xb0, 0x5d, 0xc7, 0xe7, 0xbd, 0xf8, 0x2f, 0x0c, 0xa8, 0x99, 0xc4, 0x1f, 0xba, 0x8e,
-	0x4f, 0x9e, 0x12, 0xab, 0x47, 0x3c, 0x74, 0x1b, 0xa0, 0xdb, 0x1f, 0xf9, 0x01, 0xf1, 0x8e, 0xed,
-	0x5e, 0xc3, 0x58, 0x35, 0xd6, 0xa6, 0xcd, 0x92, 0xa0, 0xec, 0xf4, 0xd0, 0x1b, 0x50, 0x1a, 0x90,
-	0xc1, 0x09, 0xef, 0xcd, 0xb1, 0xde, 0x59, 0x4e, 0xd8, 0xe9, 0xa1, 0x26, 0xcc, 0x7a, 0x64, 0x6c,
-	0xfb, 0xb6, 0xeb, 0x34, 0xf2, 0xab, 0xc6, 0x5a, 0xde, 0x0c, 0xdb, 0x74, 0xa0, 0x67, 0xbd, 0x0c,
-	0x8e, 0x03, 0xe2, 0x0d, 0x1a, 0xd3, 0x7c, 0x20, 0x25, 0x74, 0x88, 0x37, 0xc0, 0x3f, 0x99, 0x81,
-	0x8a, 0x69, 0x39, 0xa7, 0xc4, 0x24, 0x3f, 0x1c, 0x11, 0x3f, 0x40, 0x75, 0xc8, 0x9f, 0x93, 0x4b,
-	0x06, 0x5f, 0x31, 0xe9, 0x4f, 0x3e, 0xde, 0x39, 0x25, 0xc7, 0xc4, 0xe1, 0xc0, 0x15, 0x3a, 0xde,
-	0x39, 0x25, 0x6d, 0xa7, 0x87, 0x16, 0x61, 0xa6, 0x6f, 0x0f, 0xec, 0x40, 0xa0, 0xf2, 0x86, 0xa6,
-	0xce, 0x74, 0x4c, 0x9d, 0x2d, 0x00, 0xdf, 0xf5, 0x82, 0x63, 0xd7, 0xeb, 0x11, 0xaf, 0x31, 0xb3,
-	0x6a, 0xac, 0xd5, 0x36, 0xdf, 0x5a, 0x57, 0x97, 0x61, 0x5d, 0x55, 0x68, 0xfd, 0xc8, 0xf5, 0x82,
-	0x03, 0xca, 0x6b, 0x96, 0x7c, 0xf9, 0x13, 0x7d, 0x08, 0x65, 0x26, 0x24, 0xb0, 0xbc, 0x53, 0x12,
-	0x34, 0x0a, 0x4c, 0xca, 0xbd, 0x6b, 0xa4, 0x74, 0x18, 0xb3, 0xc9, 0xe0, 0xf9, 0x6f, 0x84, 0xa1,
-	0xe2, 0x13, 0xcf, 0xb6, 0xfa, 0xf6, 0x17, 0xd6, 0x49, 0x9f, 0x34, 0x8a, 0xab, 0xc6, 0xda, 0xac,
-	0xa9, 0xd1, 0xe8, 0xfc, 0xcf, 0xc9, 0xa5, 0x7f, 0xec, 0x3a, 0xfd, 0xcb, 0xc6, 0x2c, 0x63, 0x98,
-	0xa5, 0x84, 0x03, 0xa7, 0x7f, 0xc9, 0x16, 0xcd, 0x1d, 0x39, 0x01, 0xef, 0x2d, 0xb1, 0xde, 0x12,
-	0xa3, 0xb0, 0xee, 0x35, 0xa8, 0x0f, 0x6c, 0xe7, 0x78, 0xe0, 0xf6, 0x8e, 0x43, 0x83, 0x00, 0x33,
-	0x48, 0x6d, 0x60, 0x3b, 0xcf, 0xdc, 0x9e, 0x29, 0xcd, 0x42, 0x39, 0xad, 0x0b, 0x9d, 0xb3, 0x2c,
-	0x38, 0xad, 0x0b, 0x95, 0x73, 0x1d, 0x16, 0xa8, 0xcc, 0xae, 0x47, 0xac, 0x80, 0x44, 0xcc, 0x15,
-	0xc6, 0x3c, 0x3f, 0xb0, 0x9d, 0x2d, 0xd6, 0xa3, 0xf1, 0x5b, 0x17, 0x09, 0xfe, 0xaa, 0xe0, 0xb7,
-	0x2e, 0x74, 0x7e, 0xbc, 0x0e, 0xa5, 0xd0, 0xe6, 0x68, 0x16, 0xa6, 0xf7, 0x0f, 0xf6, 0xdb, 0xf5,
-	0x29, 0x04, 0x50, 0x68, 0x1d, 0x6d, 0xb5, 0xf7, 0xb7, 0xeb, 0x06, 0x2a, 0x43, 0x71, 0xbb, 0xcd,
-	0x1b, 0x39, 0xfc, 0x18, 0x20, 0xb2, 0x2e, 0x2a, 0x42, 0x7e, 0xb7, 0xfd, 0x59, 0x7d, 0x8a, 0xf2,
-	0xbc, 0x68, 0x9b, 0x47, 0x3b, 0x07, 0xfb, 0x75, 0x83, 0x0e, 0xde, 0x32, 0xdb, 0xad, 0x4e, 0xbb,
-	0x9e, 0xa3, 0x1c, 0xcf, 0x0e, 0xb6, 0xeb, 0x79, 0x54, 0x82, 0x99, 0x17, 0xad, 0xbd, 0xe7, 0xed,
-	0xfa, 0x34, 0xfe, 0xb9, 0x01, 0x55, 0xb1, 0x5e, 0xfc, 0x4c, 0xa0, 0xef, 0x40, 0xe1, 0x8c, 0x9d,
-	0x0b, 0xb6, 0x15, 0xcb, 0x9b, 0xb7, 0x62, 0x8b, 0xab, 0x9d, 0x1d, 0x53, 0xf0, 0x22, 0x0c, 0xf9,
-	0xf3, 0xb1, 0xdf, 0xc8, 0xad, 0xe6, 0xd7, 0xca, 0x9b, 0xf5, 0x75, 0x7e, 0x5e, 0xd7, 0x77, 0xc9,
-	0xe5, 0x0b, 0xab, 0x3f, 0x22, 0x26, 0xed, 0x44, 0x08, 0xa6, 0x07, 0xae, 0x47, 0xd8, 0x8e, 0x9d,
-	0x35, 0xd9, 0x6f, 0xba, 0x8d, 0xd9, 0xa2, 0x89, 0xdd, 0xca, 0x1b, 0xf8, 0x97, 0x06, 0xc0, 0xe1,
-	0x28, 0xc8, 0x3e, 0x1a, 0x8b, 0x30, 0x33, 0xa6, 0x82, 0xc5, 0xb1, 0xe0, 0x0d, 0x76, 0x26, 0x88,
-	0xe5, 0x93, 0xf0, 0x4c, 0xd0, 0x06, 0xba, 0x01, 0xc5, 0xa1, 0x47, 0xc6, 0xc7, 0xe7, 0x63, 0x06,
-	0x32, 0x6b, 0x16, 0x68, 0x73, 0x77, 0x8c, 0xde, 0x84, 0x8a, 0x7d, 0xea, 0xb8, 0x1e, 0x39, 0xe6,
-	0xb2, 0x66, 0x58, 0x6f, 0x99, 0xd3, 0x98, 0xde, 0x0a, 0x0b, 0x17, 0x5c, 0x50, 0x59, 0xf6, 0x28,
-	0x09, 0x3b, 0x50, 0x66, 0xaa, 0x4e, 0x64, 0xbe, 0x77, 0x22, 0x1d, 0x73, 0x6c, 0x58, 0xd2, 0x84,
-	0x42, 0x6b, 0xfc, 0x03, 0x40, 0xdb, 0xa4, 0x4f, 0x02, 0x32, 0x89, 0xf7, 0x50, 0x6c, 0x92, 0x57,
-	0x6d, 0x82, 0x7f, 0x66, 0xc0, 0x82, 0x26, 0x7e, 0xa2, 0x69, 0x35, 0xa0, 0xd8, 0x63, 0xc2, 0xb8,
-	0x06, 0x79, 0x53, 0x36, 0xd1, 0x43, 0x98, 0x15, 0x0a, 0xf8, 0x8d, 0x7c, 0xc6, 0xa6, 0x29, 0x72,
-	0x9d, 0x7c, 0xfc, 0xcb, 0x1c, 0x94, 0xc4, 0x44, 0x0f, 0x86, 0xa8, 0x05, 0x55, 0x8f, 0x37, 0x8e,
-	0xd9, 0x7c, 0x84, 0x46, 0xcd, 0x6c, 0x27, 0xf4, 0x74, 0xca, 0xac, 0x88, 0x21, 0x8c, 0x8c, 0x7e,
-	0x17, 0xca, 0x52, 0xc4, 0x70, 0x14, 0x08, 0x93, 0x37, 0x74, 0x01, 0xd1, 0xfe, 0x7b, 0x3a, 0x65,
-	0x82, 0x60, 0x3f, 0x1c, 0x05, 0xa8, 0x03, 0x8b, 0x72, 0x30, 0x9f, 0x8d, 0x50, 0x23, 0xcf, 0xa4,
-	0xac, 0xea, 0x52, 0x92, 0x4b, 0xf5, 0x74, 0xca, 0x44, 0x62, 0xbc, 0xd2, 0xa9, 0xaa, 0x14, 0x5c,
-	0x70, 0xe7, 0x9d, 0x50, 0xa9, 0x73, 0xe1, 0x24, 0x55, 0xea, 0x5c, 0x38, 0x8f, 0x4b, 0x50, 0x14,
-	0x2d, 0xfc, 0xcf, 0x39, 0x00, 0xb9, 0x1a, 0x07, 0x43, 0xb4, 0x0d, 0x35, 0x4f, 0xb4, 0x34, 0x6b,
-	0xbd, 0x91, 0x6a, 0x2d, 0xb1, 0x88, 0x53, 0x66, 0x55, 0x0e, 0xe2, 0xca, 0x7d, 0x0f, 0x2a, 0xa1,
-	0x94, 0xc8, 0x60, 0x37, 0x53, 0x0c, 0x16, 0x4a, 0x28, 0xcb, 0x01, 0xd4, 0x64, 0x9f, 0xc0, 0x52,
-	0x38, 0x3e, 0xc5, 0x66, 0x6f, 0x5e, 0x61, 0xb3, 0x50, 0xe0, 0x82, 0x94, 0xa0, 0x5a, 0x4d, 0x55,
-	0x2c, 0x32, 0xdb, 0xcd, 0x14, 0xb3, 0x25, 0x15, 0xa3, 0x86, 0x03, 0x1a, 0x2f, 0x79, 0x13, 0xff,
-	0x4f, 0x1e, 0x8a, 0x5b, 0xee, 0x60, 0x68, 0x79, 0x74, 0x35, 0x0a, 0x1e, 0xf1, 0x47, 0xfd, 0x80,
-	0x99, 0xab, 0xb6, 0x79, 0x57, 0x97, 0x28, 0xd8, 0xe4, 0x5f, 0x93, 0xb1, 0x9a, 0x62, 0x08, 0x1d,
-	0x2c, 0xc2, 0x63, 0xee, 0x35, 0x06, 0x8b, 0xe0, 0x28, 0x86, 0xc8, 0x83, 0x9c, 0x8f, 0x0e, 0x72,
-	0x13, 0x8a, 0x63, 0xe2, 0x45, 0x21, 0xfd, 0xe9, 0x94, 0x29, 0x09, 0xe8, 0x1d, 0x98, 0x8b, 0x87,
-	0x97, 0x19, 0xc1, 0x53, 0xeb, 0xea, 0xd1, 0xe8, 0x2e, 0x54, 0xb4, 0x18, 0x57, 0x10, 0x7c, 0xe5,
-	0x81, 0x12, 0xe2, 0x96, 0xa5, 0x5f, 0xa5, 0xf1, 0xb8, 0xf2, 0x74, 0x4a, 0x7a, 0xd6, 0x65, 0xe9,
-	0x59, 0x67, 0xc5, 0x28, 0xe1, 0x5b, 0x35, 0x27, 0xf3, 0x7d, 0xdd, 0xc9, 0xe0, 0xef, 0x43, 0x55,
-	0x33, 0x10, 0x8d, 0x3b, 0xed, 0x8f, 0x9f, 0xb7, 0xf6, 0x78, 0x90, 0x7a, 0xc2, 0xe2, 0x92, 0x59,
-	0x37, 0x68, 0xac, 0xdb, 0x6b, 0x1f, 0x1d, 0xd5, 0x73, 0xa8, 0x0a, 0xa5, 0xfd, 0x83, 0xce, 0x31,
-	0xe7, 0xca, 0xe3, 0x27, 0xa1, 0x04, 0x11, 0xe4, 0x94, 0xd8, 0x36, 0xa5, 0xc4, 0x36, 0x43, 0xc6,
-	0xb6, 0x5c, 0x14, 0xdb, 0x58, 0x98, 0xdb, 0x6b, 0xb7, 0x8e, 0xda, 0xf5, 0xe9, 0xc7, 0x35, 0xa8,
-	0x70, 0xfb, 0x1e, 0x8f, 0x1c, 0x1a, 0x6a, 0xff, 0xd1, 0x00, 0x88, 0x4e, 0x13, 0xda, 0x80, 0x62,
-	0x97, 0xe3, 0x34, 0x0c, 0xe6, 0x8c, 0x96, 0x52, 0x97, 0xcc, 0x94, 0x5c, 0xe8, 0x5b, 0x50, 0xf4,
-	0x47, 0xdd, 0x2e, 0xf1, 0x65, 0xc8, 0xbb, 0x11, 0xf7, 0x87, 0xc2, 0x5b, 0x99, 0x92, 0x8f, 0x0e,
-	0x79, 0x69, 0xd9, 0xfd, 0x11, 0x0b, 0x80, 0x57, 0x0f, 0x11, 0x7c, 0xf8, 0x6f, 0x0d, 0x28, 0x2b,
-	0x9b, 0xf7, 0xb7, 0x74, 0xc2, 0xb7, 0xa0, 0xc4, 0x74, 0x20, 0x3d, 0xe1, 0x86, 0x67, 0xcd, 0x88,
-	0x80, 0x7e, 0x07, 0x4a, 0xf2, 0x04, 0x48, 0x4f, 0xdc, 0x48, 0x17, 0x7b, 0x30, 0x34, 0x23, 0x56,
-	0xbc, 0x0b, 0xf3, 0xcc, 0x2a, 0x5d, 0x9a, 0x5c, 0x4b, 0x3b, 0xaa, 0xe9, 0xa7, 0x11, 0x4b, 0x3f,
-	0x9b, 0x30, 0x3b, 0x3c, 0xbb, 0xf4, 0xed, 0xae, 0xd5, 0x17, 0x5a, 0x84, 0x6d, 0xfc, 0x11, 0x20,
-	0x55, 0xd8, 0x24, 0xd3, 0xc5, 0x55, 0x28, 0x3f, 0xb5, 0xfc, 0x33, 0xa1, 0x12, 0x7e, 0x08, 0x55,
-	0xda, 0xdc, 0x7d, 0xf1, 0x1a, 0x3a, 0xb2, 0xcb, 0x81, 0xe4, 0x9e, 0xc8, 0xe6, 0x08, 0xa6, 0xcf,
-	0x2c, 0xff, 0x8c, 0x4d, 0xb4, 0x6a, 0xb2, 0xdf, 0xe8, 0x1d, 0xa8, 0x77, 0xf9, 0x24, 0x8f, 0x63,
-	0x57, 0x86, 0x39, 0x41, 0x0f, 0x33, 0xc1, 0x4f, 0xa1, 0xc2, 0xe7, 0xf0, 0x55, 0x2b, 0x81, 0xe7,
-	0x61, 0xee, 0xc8, 0xb1, 0x86, 0xfe, 0x99, 0x2b, 0xa3, 0x1b, 0xfe, 0x07, 0x03, 0xea, 0x11, 0x6d,
-	0x22, 0xc4, 0xb7, 0x61, 0xce, 0x23, 0x03, 0xcb, 0x76, 0x6c, 0xe7, 0xf4, 0xf8, 0xe4, 0x32, 0x20,
-	0xbe, 0xb8, 0x30, 0xd5, 0x42, 0xf2, 0x63, 0x4a, 0xa5, 0xaa, 0x9d, 0xf4, 0xdd, 0x13, 0xe1, 0xe6,
-	0xd8, 0x6f, 0x9a, 0x2c, 0xa8, 0x7e, 0xae, 0x14, 0x7a, 0x39, 0xfc, 0xd3, 0x1c, 0x54, 0x3e, 0xb1,
-	0x82, 0xae, 0x5c, 0x54, 0xb4, 0x03, 0xb5, 0xd0, 0xed, 0x31, 0x8a, 0xd0, 0x32, 0x16, 0x7c, 0xd9,
-	0x18, 0x99, 0x64, 0xcb, 0xb8, 0x59, 0xed, 0xaa, 0x04, 0x26, 0xca, 0x72, 0xba, 0xa4, 0x1f, 0x8a,
-	0xca, 0x65, 0x8b, 0x62, 0x8c, 0xaa, 0x28, 0x95, 0x80, 0x0e, 0xa0, 0x3e, 0xf4, 0xdc, 0x53, 0x8f,
-	0xf8, 0x7e, 0x28, 0x8c, 0x07, 0x38, 0x9c, 0x22, 0xec, 0x50, 0xb0, 0x46, 0xe2, 0xe6, 0x86, 0x3a,
-	0xe9, 0xf1, 0x5c, 0x94, 0xe9, 0x70, 0xb7, 0xf5, 0x1f, 0x39, 0x40, 0xc9, 0x49, 0xfd, 0xa6, 0xc9,
-	0xdf, 0x3d, 0xa8, 0xf9, 0x81, 0xe5, 0x25, 0xb6, 0x61, 0x95, 0x51, 0xc3, 0x58, 0xf0, 0x36, 0x84,
-	0x0a, 0x1d, 0x3b, 0x6e, 0x60, 0xbf, 0xbc, 0x14, 0xf9, 0x73, 0x4d, 0x92, 0xf7, 0x19, 0x15, 0xb5,
-	0xa1, 0xf8, 0xd2, 0xee, 0x07, 0xc4, 0xf3, 0x1b, 0x33, 0xab, 0xf9, 0xb5, 0xda, 0xe6, 0xc3, 0xeb,
-	0x96, 0x61, 0xfd, 0x43, 0xc6, 0xdf, 0xb9, 0x1c, 0x12, 0x53, 0x8e, 0x55, 0x73, 0xd2, 0x82, 0x96,
-	0xa7, 0xdf, 0x84, 0xd9, 0x57, 0x54, 0x04, 0xbd, 0x7f, 0x17, 0x79, 0x1a, 0xc9, 0xda, 0xfc, 0xfa,
-	0xfd, 0xd2, 0xb3, 0x4e, 0x07, 0xc4, 0x09, 0xe4, 0x0d, 0x51, 0xb6, 0xf1, 0x3d, 0x80, 0x08, 0x86,
-	0x06, 0x83, 0xfd, 0x83, 0xc3, 0xe7, 0x9d, 0xfa, 0x14, 0xaa, 0xc0, 0xec, 0xfe, 0xc1, 0x76, 0x7b,
-	0xaf, 0x4d, 0x23, 0x07, 0xde, 0x90, 0x26, 0xd5, 0xd6, 0x52, 0xc5, 0x34, 0x34, 0x4c, 0xbc, 0x0c,
-	0x8b, 0x69, 0x0b, 0x48, 0xb3, 0xd4, 0xaa, 0xd8, 0xa5, 0x13, 0x1d, 0x22, 0x15, 0x3a, 0xa7, 0x4f,
-	0xb7, 0x01, 0x45, 0xbe, 0x7b, 0x7b, 0x22, 0x6d, 0x97, 0x4d, 0x6a, 0x08, 0xbe, 0x19, 0x49, 0x4f,
-	0xac, 0x52, 0xd8, 0x4e, 0x75, 0x3c, 0x33, 0xa9, 0x8e, 0x07, 0xdd, 0x85, 0x6a, 0x78, 0x1a, 0x2c,
-	0x5f, 0x64, 0x09, 0x25, 0xb3, 0x22, 0x37, 0x3a, 0xa5, 0x69, 0x46, 0x2f, 0xea, 0x46, 0x47, 0xf7,
-	0xa0, 0x40, 0xc6, 0xc4, 0x09, 0xfc, 0x46, 0x99, 0xc5, 0x92, 0xaa, 0xcc, 0xea, 0xdb, 0x94, 0x6a,
-	0x8a, 0x4e, 0xfc, 0x5d, 0x98, 0x67, 0xb7, 0xa7, 0x27, 0x9e, 0xe5, 0xa8, 0xd7, 0xbc, 0x4e, 0x67,
-	0x4f, 0x98, 0x9b, 0xfe, 0x44, 0x35, 0xc8, 0xed, 0x6c, 0x0b, 0x23, 0xe4, 0x76, 0xb6, 0xf1, 0x8f,
-	0x0d, 0x40, 0xea, 0xb8, 0x89, 0xec, 0x1c, 0x13, 0x2e, 0xe1, 0xf3, 0x11, 0xfc, 0x22, 0xcc, 0x10,
-	0xcf, 0x73, 0x3d, 0xe1, 0x8f, 0x78, 0x03, 0xbf, 0x25, 0x74, 0x30, 0xc9, 0xd8, 0x3d, 0x0f, 0xcf,
-	0x20, 0x97, 0x66, 0x84, 0xaa, 0xee, 0xc2, 0x82, 0xc6, 0x35, 0x51, 0x4c, 0xfb, 0x10, 0xe6, 0x98,
-	0xb0, 0xad, 0x33, 0xd2, 0x3d, 0x1f, 0xba, 0xb6, 0x93, 0xc0, 0xa3, 0x2b, 0x17, 0xb9, 0x5e, 0x3a,
-	0x0f, 0x3e, 0xb1, 0x4a, 0x48, 0xec, 0x74, 0xf6, 0xf0, 0x67, 0xb0, 0x1c, 0x93, 0x23, 0xd5, 0xff,
-	0x03, 0x28, 0x77, 0x43, 0xa2, 0x2f, 0xb2, 0xa0, 0xdb, 0xba, 0x72, 0xf1, 0xa1, 0xea, 0x08, 0x7c,
-	0x00, 0x37, 0x12, 0xa2, 0x27, 0x9a, 0xf3, 0xdb, 0xb0, 0xc4, 0x04, 0xee, 0x12, 0x32, 0x6c, 0xf5,
-	0xed, 0x71, 0xa6, 0xa5, 0x87, 0x62, 0x52, 0x0a, 0xe3, 0xd7, 0xbb, 0x2f, 0xf0, 0xef, 0x09, 0xc4,
-	0x8e, 0x3d, 0x20, 0x1d, 0x77, 0x2f, 0x5b, 0x37, 0x1a, 0xe7, 0xce, 0xc9, 0xa5, 0x2f, 0x12, 0x1e,
-	0xf6, 0x1b, 0xff, 0x93, 0x21, 0x4c, 0xa5, 0x0e, 0xff, 0x9a, 0x77, 0xf2, 0x0a, 0xc0, 0x29, 0x3d,
-	0x32, 0xa4, 0x47, 0x3b, 0x78, 0xad, 0x45, 0xa1, 0x84, 0x7a, 0x52, 0xff, 0x5d, 0x11, 0x7a, 0x2e,
-	0x8a, 0x7d, 0xce, 0xfe, 0x09, 0xbd, 0xdc, 0x6d, 0x28, 0x33, 0xc2, 0x51, 0x60, 0x05, 0x23, 0x3f,
-	0xb1, 0x18, 0x7f, 0x26, 0xb6, 0xbd, 0x1c, 0x34, 0xd1, 0xbc, 0xbe, 0x05, 0x05, 0x76, 0xcd, 0x90,
-	0x49, 0xf6, 0xcd, 0x94, 0xfd, 0xc8, 0xf5, 0x30, 0x05, 0x23, 0xfe, 0xa9, 0x01, 0x85, 0x67, 0xac,
-	0x38, 0xab, 0xa8, 0x36, 0x2d, 0xd7, 0xc2, 0xb1, 0x06, 0xbc, 0x64, 0x54, 0x32, 0xd9, 0x6f, 0x96,
-	0x94, 0x12, 0xe2, 0x3d, 0x37, 0xf7, 0x78, 0xf2, 0x5b, 0x32, 0xc3, 0x36, 0xb5, 0x59, 0xb7, 0x6f,
-	0x13, 0x27, 0x60, 0xbd, 0xd3, 0xac, 0x57, 0xa1, 0xd0, 0xbc, 0xda, 0xf6, 0xf7, 0x88, 0xe5, 0x39,
-	0xa2, 0x9c, 0x3a, 0x6b, 0x46, 0x04, 0xbc, 0x07, 0x75, 0xae, 0x47, 0xab, 0xd7, 0x53, 0x52, 0xcf,
-	0x10, 0xcd, 0x88, 0xa1, 0x69, 0xd2, 0x72, 0x71, 0x69, 0xbf, 0x30, 0x60, 0x5e, 0x11, 0x37, 0x91,
-	0x55, 0xdf, 0x85, 0x02, 0x2f, 0x5f, 0x8b, 0x4c, 0x67, 0x51, 0x1f, 0xc5, 0x61, 0x4c, 0xc1, 0x83,
-	0xd6, 0xa1, 0xc8, 0x7f, 0xc9, 0xdb, 0x41, 0x3a, 0xbb, 0x64, 0xc2, 0xf7, 0x60, 0x41, 0x90, 0xc8,
-	0xc0, 0x4d, 0x3b, 0x18, 0x6c, 0x31, 0xf0, 0x9f, 0xc0, 0xa2, 0xce, 0x36, 0xd1, 0x94, 0x14, 0x25,
-	0x73, 0xaf, 0xa3, 0x64, 0x4b, 0x2a, 0xf9, 0x7c, 0xd8, 0x53, 0xf2, 0xa8, 0xf8, 0x8e, 0x51, 0xd7,
-	0x2b, 0xa7, 0xaf, 0x57, 0x34, 0x01, 0x29, 0xe2, 0x1b, 0x9d, 0xc0, 0x07, 0x72, 0x3b, 0xec, 0xd9,
-	0x7e, 0xe8, 0xc3, 0x31, 0x54, 0xfa, 0xb6, 0x43, 0x2c, 0x4f, 0xd4, 0xd4, 0x0d, 0x5e, 0x53, 0x57,
-	0x69, 0xf8, 0x0b, 0x40, 0xea, 0xc0, 0x6f, 0x54, 0xe9, 0xfb, 0xd2, 0x64, 0x87, 0x9e, 0x3b, 0x70,
-	0x33, 0xcd, 0x8e, 0xff, 0x14, 0x96, 0x62, 0x7c, 0xdf, 0xa8, 0x9a, 0x0b, 0x30, 0xbf, 0x4d, 0x64,
-	0x42, 0x23, 0xdd, 0xde, 0x47, 0x80, 0x54, 0xe2, 0x44, 0x91, 0x6d, 0x03, 0xe6, 0x9f, 0xb9, 0x63,
-	0xea, 0x22, 0x29, 0x35, 0xf2, 0x0d, 0xbc, 0x42, 0x11, 0x9a, 0x22, 0x6c, 0x53, 0x70, 0x75, 0xc0,
-	0x44, 0xe0, 0xff, 0x66, 0x40, 0xa5, 0xd5, 0xb7, 0xbc, 0x81, 0x04, 0xfe, 0x1e, 0x14, 0xf8, 0xbd,
-	0x5b, 0x94, 0xba, 0xee, 0xeb, 0x62, 0x54, 0x5e, 0xde, 0x68, 0xf1, 0x5b, 0xba, 0x18, 0x45, 0x15,
-	0x17, 0xaf, 0x61, 0xdb, 0xb1, 0xd7, 0xb1, 0x6d, 0xf4, 0x1e, 0xcc, 0x58, 0x74, 0x08, 0x0b, 0x45,
-	0xb5, 0x78, 0xc5, 0x83, 0x49, 0x63, 0x77, 0x00, 0xce, 0x85, 0xbf, 0x03, 0x65, 0x05, 0x01, 0x15,
-	0x21, 0xff, 0xa4, 0x2d, 0x12, 0xf6, 0xd6, 0x56, 0x67, 0xe7, 0x05, 0x2f, 0xf5, 0xd4, 0x00, 0xb6,
-	0xdb, 0x61, 0x3b, 0x87, 0x3f, 0x15, 0xa3, 0x84, 0xdb, 0x57, 0xf5, 0x31, 0xb2, 0xf4, 0xc9, 0xbd,
-	0x96, 0x3e, 0x17, 0x50, 0x15, 0xd3, 0x9f, 0x34, 0x8c, 0x31, 0x79, 0x19, 0x61, 0x4c, 0x51, 0xde,
-	0x14, 0x8c, 0xf8, 0x57, 0x06, 0xd4, 0xb7, 0xdd, 0x57, 0xce, 0xa9, 0x67, 0xf5, 0xc2, 0x73, 0xf2,
-	0x61, 0x6c, 0xa5, 0xd6, 0x63, 0x65, 0xd3, 0x18, 0x7f, 0x44, 0x88, 0xad, 0x98, 0x72, 0xd1, 0xce,
-	0xe9, 0x17, 0xed, 0x0f, 0x60, 0x2e, 0x36, 0x88, 0xda, 0xfe, 0x45, 0x6b, 0x6f, 0x67, 0x9b, 0xda,
-	0x9a, 0x95, 0xdc, 0xda, 0xfb, 0xad, 0xc7, 0x7b, 0x6d, 0xf1, 0xb4, 0xd4, 0xda, 0xdf, 0x6a, 0xef,
-	0xd5, 0x73, 0xb8, 0x0b, 0xf3, 0x0a, 0xfc, 0xa4, 0x6f, 0x06, 0x19, 0xda, 0xcd, 0x41, 0x55, 0x44,
-	0x7b, 0x71, 0x28, 0xff, 0x35, 0x07, 0x35, 0x49, 0xf9, 0x7a, 0x30, 0xd1, 0x32, 0x14, 0x7a, 0x27,
-	0x47, 0xf6, 0x17, 0xf2, 0x4d, 0x49, 0xb4, 0x28, 0xbd, 0xcf, 0x71, 0xf8, 0xc3, 0xae, 0x68, 0xd1,
-	0x30, 0xee, 0x59, 0x2f, 0x83, 0x1d, 0xa7, 0x47, 0x2e, 0x58, 0x52, 0x30, 0x6d, 0x46, 0x04, 0x56,
-	0x7b, 0x12, 0x0f, 0xc0, 0xec, 0x66, 0xa5, 0x3c, 0x08, 0xa3, 0x07, 0x50, 0xa7, 0xbf, 0x5b, 0xc3,
-	0x61, 0xdf, 0x26, 0x3d, 0x2e, 0xa0, 0xc8, 0x78, 0x12, 0x74, 0x8a, 0xce, 0xee, 0x22, 0x7e, 0x63,
-	0x96, 0x85, 0x25, 0xd1, 0x42, 0xab, 0x50, 0xe6, 0xfa, 0xed, 0x38, 0xcf, 0x7d, 0xc2, 0x5e, 0x45,
-	0xf3, 0xa6, 0x4a, 0xd2, 0xd3, 0x0c, 0x88, 0xa7, 0x19, 0x0b, 0x30, 0xdf, 0x1a, 0x05, 0x67, 0x6d,
-	0x87, 0xc6, 0x0a, 0x69, 0xe5, 0x45, 0x40, 0x94, 0xb8, 0x6d, 0xfb, 0x2a, 0x55, 0xb0, 0xea, 0x0b,
-	0xd2, 0x86, 0x05, 0x4a, 0x24, 0x4e, 0x60, 0x77, 0x95, 0xb8, 0x2a, 0x33, 0x2f, 0x23, 0x96, 0x79,
-	0x59, 0xbe, 0xff, 0xca, 0xf5, 0x7a, 0xc2, 0xe6, 0x61, 0x1b, 0xff, 0xbd, 0xc1, 0x21, 0x9f, 0xfb,
-	0x5a, 0xfa, 0xf4, 0x1b, 0x8a, 0x41, 0xef, 0x43, 0xd1, 0x1d, 0xb2, 0xb7, 0x7f, 0x51, 0x86, 0x59,
-	0x5e, 0xe7, 0x5f, 0x0b, 0xac, 0x0b, 0xc1, 0x07, 0xbc, 0xd7, 0x94, 0x6c, 0xe8, 0x3e, 0xd4, 0xce,
-	0x2c, 0xff, 0x8c, 0xf4, 0x0e, 0xa5, 0x4c, 0x7e, 0xf3, 0x8b, 0x51, 0xf1, 0x5a, 0xa4, 0xdf, 0x13,
-	0x12, 0x5c, 0xa1, 0x1f, 0x7e, 0x08, 0x4b, 0x92, 0x53, 0xbc, 0x5b, 0x5c, 0xc1, 0xfc, 0x0a, 0x6e,
-	0x4b, 0xe6, 0xad, 0x33, 0xcb, 0x39, 0x25, 0x12, 0xf0, 0xb7, 0xb5, 0x40, 0x72, 0x3e, 0xf9, 0xd4,
-	0xf9, 0x3c, 0x86, 0x46, 0x38, 0x1f, 0x76, 0xb3, 0x76, 0xfb, 0xaa, 0xa2, 0x23, 0x5f, 0x9c, 0xa7,
-	0x92, 0xc9, 0x7e, 0x53, 0x9a, 0xe7, 0xf6, 0xc3, 0x54, 0x9a, 0xfe, 0xc6, 0x5b, 0x70, 0x53, 0xca,
-	0x10, 0x77, 0x5e, 0x5d, 0x48, 0x42, 0xf1, 0x34, 0x21, 0xc2, 0xb0, 0x74, 0xe8, 0xd5, 0x0b, 0xaf,
-	0x72, 0xea, 0x4b, 0xc0, 0x64, 0x1a, 0x8a, 0xcc, 0x25, 0xbe, 0x29, 0xa9, 0x62, 0x4a, 0xb6, 0x24,
-	0xc9, 0x54, 0x80, 0x4a, 0x16, 0x0b, 0x46, 0xc9, 0x89, 0x05, 0x4b, 0x88, 0xfe, 0x01, 0xac, 0x84,
-	0x4a, 0x50, 0xbb, 0x1d, 0x12, 0x6f, 0x60, 0xfb, 0xbe, 0x52, 0x11, 0x4f, 0x9b, 0xf8, 0x7d, 0x98,
-	0x1e, 0x12, 0x11, 0x84, 0xca, 0x9b, 0x48, 0x6e, 0x4a, 0x65, 0x30, 0xeb, 0xc7, 0x3d, 0xb8, 0x23,
-	0xa5, 0x73, 0x8b, 0xa6, 0x8a, 0x8f, 0x2b, 0x25, 0xab, 0x81, 0xb9, 0x8c, 0x6a, 0x60, 0x3e, 0xf6,
-	0x4a, 0xf3, 0x11, 0x37, 0xa4, 0x3c, 0xf3, 0x13, 0x25, 0x17, 0xbb, 0xdc, 0xa6, 0xa1, 0xab, 0x98,
-	0x48, 0xd8, 0x5f, 0x0a, 0x2f, 0xf0, 0x55, 0x79, 0x78, 0xc2, 0x66, 0x28, 0x9f, 0x40, 0x64, 0x93,
-	0x66, 0xcd, 0x74, 0x01, 0x4c, 0xb5, 0x16, 0x3a, 0x6d, 0x6a, 0x34, 0x7c, 0x02, 0x8b, 0xba, 0x5f,
-	0x9b, 0x48, 0x97, 0x45, 0x98, 0x09, 0xdc, 0x73, 0x22, 0x63, 0x0d, 0x6f, 0x48, 0xdb, 0x85, 0x3e,
-	0x6f, 0x22, 0xdb, 0x59, 0x91, 0x30, 0x76, 0x3a, 0x26, 0xd5, 0x97, 0x6e, 0x2c, 0x79, 0x07, 0xe2,
-	0x0d, 0xbc, 0x0f, 0xcb, 0x71, 0xcf, 0x36, 0x91, 0xca, 0x2f, 0xf8, 0x59, 0x4a, 0x73, 0x7e, 0x13,
-	0xc9, 0xfd, 0x38, 0xf2, 0x4b, 0x8a, 0x6f, 0x9b, 0x48, 0xa4, 0x09, 0xcd, 0x34, 0x57, 0xf7, 0x55,
-	0x1c, 0x9d, 0xd0, 0xf3, 0x4d, 0x24, 0xcc, 0x8f, 0x84, 0x4d, 0xbe, 0xfc, 0x91, 0xbb, 0xca, 0x5f,
-	0xe9, 0xae, 0xc4, 0x21, 0x89, 0x1c, 0xea, 0xd7, 0xb0, 0xe9, 0x04, 0x46, 0xe4, 0xcb, 0x27, 0xc5,
-	0xa0, 0xe1, 0x2c, 0xc4, 0x60, 0x0d, 0xb9, 0xb1, 0xd5, 0x08, 0x30, 0xd1, 0x62, 0x7c, 0x12, 0xb9,
-	0xf1, 0x44, 0x90, 0x98, 0x48, 0xf0, 0xa7, 0xb0, 0x9a, 0x1d, 0x1f, 0x26, 0x91, 0xfc, 0x60, 0x03,
-	0x4a, 0xe1, 0x65, 0x48, 0xf9, 0x12, 0xad, 0x0c, 0xc5, 0xfd, 0x83, 0xa3, 0xc3, 0xd6, 0x56, 0x9b,
-	0x7f, 0x8a, 0xb6, 0x75, 0x60, 0x9a, 0xcf, 0x0f, 0x3b, 0xf5, 0xdc, 0xe6, 0xaf, 0xf3, 0x90, 0xdb,
-	0x7d, 0x81, 0x3e, 0x83, 0x19, 0xfe, 0x5d, 0xc6, 0x15, 0x1f, 0xe3, 0x34, 0xaf, 0xfa, 0xf4, 0x04,
-	0xdf, 0xf8, 0xf1, 0x7f, 0xfe, 0xfa, 0xe7, 0xb9, 0x79, 0x5c, 0xd9, 0x18, 0x7f, 0x7b, 0xe3, 0x7c,
-	0xbc, 0xc1, 0xc2, 0xd4, 0x23, 0xe3, 0x01, 0xfa, 0x18, 0xf2, 0x87, 0xa3, 0x00, 0x65, 0x7e, 0xa4,
-	0xd3, 0xcc, 0xfe, 0x1a, 0x05, 0x2f, 0x31, 0xa1, 0x73, 0x18, 0x84, 0xd0, 0xe1, 0x28, 0xa0, 0x22,
-	0x7f, 0x08, 0x65, 0xf5, 0x5b, 0x92, 0x6b, 0xbf, 0xdc, 0x69, 0x5e, 0xff, 0x9d, 0x0a, 0xbe, 0xcd,
-	0xa0, 0x6e, 0x60, 0x24, 0xa0, 0xf8, 0xd7, 0x2e, 0xea, 0x2c, 0x3a, 0x17, 0x0e, 0xca, 0xfc, 0xae,
-	0xa7, 0x99, 0xfd, 0xe9, 0x4a, 0x62, 0x16, 0xc1, 0x85, 0x43, 0x45, 0xfe, 0x91, 0xf8, 0x6a, 0xa5,
-	0x1b, 0xa0, 0x3b, 0x29, 0x5f, 0x2d, 0xa8, 0xef, 0xf3, 0xcd, 0xd5, 0x6c, 0x06, 0x01, 0x72, 0x8b,
-	0x81, 0x2c, 0xe3, 0x79, 0x01, 0xd2, 0x0d, 0x59, 0x1e, 0x19, 0x0f, 0x36, 0xbb, 0x30, 0xc3, 0x5e,
-	0xb8, 0xd0, 0xe7, 0xf2, 0x47, 0x33, 0xe5, 0xa9, 0x2f, 0x63, 0xa1, 0xb5, 0xb7, 0x31, 0xbc, 0xc8,
-	0x80, 0x6a, 0xb8, 0x44, 0x81, 0xd8, 0xfb, 0xd6, 0x23, 0xe3, 0xc1, 0x9a, 0xf1, 0xbe, 0xb1, 0xf9,
-	0xab, 0x19, 0x98, 0x61, 0xa5, 0x5d, 0x74, 0x0e, 0x10, 0xbd, 0xf6, 0xc4, 0x67, 0x97, 0x78, 0x3f,
-	0x8a, 0xcf, 0x2e, 0xf9, 0x50, 0x84, 0x9b, 0x0c, 0x74, 0x11, 0xcf, 0x51, 0x50, 0x56, 0x31, 0xde,
-	0x60, 0x45, 0x70, 0x6a, 0xc7, 0xbf, 0x32, 0x44, 0x65, 0x9b, 0x9f, 0x25, 0x94, 0x26, 0x4d, 0x7b,
-	0xf2, 0x89, 0x6f, 0x87, 0x94, 0xe7, 0x1e, 0xfc, 0x5d, 0x06, 0xb8, 0x81, 0xeb, 0x11, 0xa0, 0xc7,
-	0x38, 0x1e, 0x19, 0x0f, 0x3e, 0x6f, 0xe0, 0x05, 0x61, 0xe5, 0x58, 0x0f, 0xfa, 0x11, 0xd4, 0xf4,
-	0x27, 0x0d, 0x74, 0x37, 0x05, 0x2b, 0xfe, 0x32, 0xd2, 0x7c, 0xeb, 0x6a, 0x26, 0xa1, 0xd3, 0x0a,
-	0xd3, 0x49, 0x80, 0x73, 0xe4, 0x73, 0x42, 0x86, 0x16, 0x65, 0x12, 0x6b, 0x80, 0xfe, 0xce, 0x10,
-	0x2f, 0x4e, 0xd1, 0x1b, 0x05, 0x4a, 0x93, 0x9e, 0x78, 0x01, 0x69, 0xde, 0xbb, 0x86, 0x4b, 0x28,
-	0xf1, 0xfb, 0x4c, 0x89, 0x0f, 0xf0, 0x62, 0xa4, 0x44, 0x60, 0x0f, 0x48, 0xe0, 0x0a, 0x2d, 0x3e,
-	0xbf, 0x85, 0x6f, 0x68, 0xc6, 0xd1, 0x7a, 0xa3, 0xc5, 0xe2, 0xef, 0x0c, 0xa9, 0x8b, 0xa5, 0xbd,
-	0x5b, 0xa4, 0x2e, 0x96, 0xfe, 0x48, 0x91, 0xb6, 0x58, 0xfc, 0x55, 0x21, 0x6d, 0xb1, 0xc2, 0x9e,
-	0xcd, 0xff, 0x9d, 0x86, 0xe2, 0x16, 0xff, 0x5a, 0x1c, 0xb9, 0x50, 0x0a, 0xcb, 0xf4, 0x68, 0x25,
-	0xad, 0xce, 0x18, 0x5d, 0x6b, 0x9a, 0x77, 0x32, 0xfb, 0x85, 0x42, 0x6f, 0x32, 0x85, 0xde, 0xc0,
-	0xcb, 0x14, 0x59, 0x7c, 0x90, 0xbe, 0xc1, 0x8b, 0x59, 0x1b, 0x56, 0xaf, 0x47, 0x0d, 0xf1, 0xc7,
-	0x50, 0x51, 0xeb, 0xe8, 0xe8, 0xcd, 0xd4, 0xda, 0xa6, 0x5a, 0x8a, 0x6f, 0xe2, 0xab, 0x58, 0x04,
-	0xf2, 0x5b, 0x0c, 0x79, 0x05, 0xdf, 0x4c, 0x41, 0xf6, 0x18, 0xab, 0x06, 0xce, 0x6b, 0xe0, 0xe9,
-	0xe0, 0x5a, 0x89, 0x3d, 0x1d, 0x5c, 0x2f, 0xa1, 0x5f, 0x09, 0x3e, 0x62, 0xac, 0x14, 0xdc, 0x07,
-	0x88, 0x2a, 0xd9, 0x28, 0xd5, 0x96, 0xca, 0xbd, 0x2e, 0xee, 0x1c, 0x92, 0x45, 0x70, 0x8c, 0x19,
-	0xac, 0xd8, 0x77, 0x31, 0xd8, 0xbe, 0xed, 0x07, 0xfc, 0x60, 0x56, 0xb5, 0xd2, 0x34, 0x4a, 0x9d,
-	0x8f, 0x5e, 0xdf, 0x6e, 0xde, 0xbd, 0x92, 0x47, 0xa0, 0xdf, 0x63, 0xe8, 0x77, 0x70, 0x33, 0x05,
-	0x7d, 0xc8, 0x79, 0xe9, 0x66, 0xfb, 0xbf, 0x02, 0x94, 0x9f, 0x59, 0xb6, 0x13, 0x10, 0xc7, 0x72,
-	0xba, 0x04, 0x9d, 0xc0, 0x0c, 0x8b, 0xd4, 0x71, 0x47, 0xac, 0x96, 0x6d, 0xe3, 0x8e, 0x58, 0xab,
-	0x69, 0xe2, 0x55, 0x06, 0xdc, 0xc4, 0x4b, 0x14, 0x78, 0x10, 0x89, 0xde, 0x60, 0xa5, 0x48, 0x3a,
-	0xe9, 0x97, 0x50, 0x10, 0xaf, 0x7d, 0x31, 0x41, 0x5a, 0xf1, 0xa7, 0x79, 0x2b, 0xbd, 0x33, 0x6d,
-	0x2f, 0xab, 0x30, 0x3e, 0xe3, 0xa3, 0x38, 0x63, 0x80, 0xa8, 0xc6, 0x1e, 0x5f, 0xd1, 0x44, 0x49,
-	0xbe, 0xb9, 0x9a, 0xcd, 0x90, 0x66, 0x53, 0x15, 0xb3, 0x17, 0xf2, 0x52, 0xdc, 0x3f, 0x84, 0xe9,
-	0xa7, 0x96, 0x7f, 0x86, 0x62, 0xb1, 0x57, 0xf9, 0x8a, 0xac, 0xd9, 0x4c, 0xeb, 0x12, 0x28, 0x77,
-	0x18, 0xca, 0x4d, 0xee, 0xca, 0x54, 0x94, 0x33, 0xcb, 0xa7, 0x41, 0x0d, 0xf5, 0xa0, 0xc0, 0x3f,
-	0x2a, 0x8b, 0xdb, 0x4f, 0xfb, 0x30, 0x2d, 0x6e, 0x3f, 0xfd, 0x3b, 0xb4, 0xeb, 0x51, 0x86, 0x30,
-	0x2b, 0xbf, 0xe2, 0x42, 0xb1, 0x87, 0xfb, 0xd8, 0x17, 0x5f, 0xcd, 0x95, 0xac, 0x6e, 0x81, 0x75,
-	0x97, 0x61, 0xdd, 0xc6, 0x8d, 0xc4, 0x5a, 0x09, 0xce, 0x47, 0xc6, 0x83, 0xf7, 0x0d, 0xf4, 0x23,
-	0x80, 0xe8, 0x59, 0x22, 0x71, 0x02, 0xe3, 0x2f, 0x1c, 0x89, 0x13, 0x98, 0x78, 0xd1, 0xc0, 0xeb,
-	0x0c, 0x77, 0x0d, 0xdf, 0x8d, 0xe3, 0x06, 0x9e, 0xe5, 0xf8, 0x2f, 0x89, 0xf7, 0x1e, 0xaf, 0xb2,
-	0xfa, 0x67, 0xf6, 0x90, 0x4e, 0xd9, 0x83, 0x52, 0x58, 0x75, 0x8e, 0x7b, 0xdb, 0x78, 0x35, 0x3c,
-	0xee, 0x6d, 0x13, 0xe5, 0x6a, 0xdd, 0xed, 0x68, 0xbb, 0x45, 0xb2, 0xd2, 0x03, 0xf8, 0x8b, 0x3a,
-	0x4c, 0xd3, 0xac, 0x9b, 0x26, 0x27, 0x51, 0xdd, 0x24, 0x3e, 0xfb, 0x44, 0x15, 0x35, 0x3e, 0xfb,
-	0x64, 0xc9, 0x45, 0x4f, 0x4e, 0xe8, 0x25, 0x6b, 0x83, 0x97, 0x28, 0xe8, 0x4c, 0x5d, 0x28, 0x2b,
-	0x85, 0x15, 0x94, 0x22, 0x4c, 0x2f, 0xcf, 0xc6, 0xc3, 0x5d, 0x4a, 0x55, 0x06, 0xbf, 0xc1, 0xf0,
-	0x96, 0x78, 0xb8, 0x63, 0x78, 0x3d, 0xce, 0x41, 0x01, 0xc5, 0xec, 0xc4, 0xb9, 0x4f, 0x99, 0x9d,
-	0x7e, 0xf6, 0x57, 0xb3, 0x19, 0x32, 0x67, 0x17, 0x1d, 0xfc, 0x57, 0x50, 0x51, 0xcb, 0x2b, 0x28,
-	0x45, 0xf9, 0x58, 0x49, 0x39, 0x1e, 0x47, 0xd2, 0xaa, 0x33, 0xba, 0x67, 0x63, 0x90, 0x96, 0xc2,
-	0x46, 0x81, 0xfb, 0x50, 0x14, 0xf5, 0x96, 0x34, 0x93, 0xea, 0xe5, 0xe7, 0x34, 0x93, 0xc6, 0x8a,
-	0x35, 0x7a, 0xf6, 0xcc, 0x10, 0xe9, 0x95, 0x52, 0xc6, 0x6a, 0x81, 0xf6, 0x84, 0x04, 0x59, 0x68,
-	0x51, 0x25, 0x33, 0x0b, 0x4d, 0xb9, 0xce, 0x67, 0xa1, 0x9d, 0x92, 0x40, 0xf8, 0x03, 0x79, 0x4d,
-	0x46, 0x19, 0xc2, 0xd4, 0xf8, 0x88, 0xaf, 0x62, 0x49, 0xbb, 0xdc, 0x44, 0x80, 0x32, 0x38, 0x5e,
-	0x00, 0x44, 0xd5, 0xa0, 0x78, 0xc6, 0x9a, 0x5a, 0x05, 0x8f, 0x67, 0xac, 0xe9, 0x05, 0x25, 0xdd,
-	0xf7, 0x45, 0xb8, 0xfc, 0x6e, 0x45, 0x91, 0x7f, 0x66, 0x00, 0x4a, 0x16, 0x8e, 0xd0, 0xc3, 0x74,
-	0xe9, 0xa9, 0xb5, 0xf5, 0xe6, 0xbb, 0xaf, 0xc7, 0x9c, 0x16, 0xce, 0x22, 0x95, 0xba, 0x8c, 0x7b,
-	0xf8, 0x8a, 0x2a, 0xf5, 0xe7, 0x06, 0x54, 0xb5, 0xaa, 0x13, 0xba, 0x9f, 0xb1, 0xa6, 0xb1, 0x92,
-	0x7b, 0xf3, 0xed, 0x6b, 0xf9, 0xd2, 0x52, 0x79, 0x65, 0x07, 0xc8, 0x3b, 0xcd, 0x4f, 0x0c, 0xa8,
-	0xe9, 0x55, 0x2a, 0x94, 0x21, 0x3b, 0x51, 0xb2, 0x6f, 0xae, 0x5d, 0xcf, 0x78, 0xf5, 0xf2, 0x44,
-	0xd7, 0x99, 0x3e, 0x14, 0x45, 0x5d, 0x2b, 0x6d, 0xe3, 0xeb, 0xc5, 0xfe, 0xb4, 0x8d, 0x1f, 0x2b,
-	0x8a, 0xa5, 0x6c, 0x7c, 0xcf, 0xed, 0x13, 0xe5, 0x98, 0x89, 0xc2, 0x57, 0x16, 0xda, 0xd5, 0xc7,
-	0x2c, 0x56, 0x35, 0xcb, 0x42, 0x8b, 0x8e, 0x99, 0xac, 0x78, 0xa1, 0x0c, 0x61, 0xd7, 0x1c, 0xb3,
-	0x78, 0xc1, 0x2c, 0xe5, 0x98, 0x31, 0x40, 0xe5, 0x98, 0x45, 0xb5, 0xa9, 0xb4, 0x63, 0x96, 0x78,
-	0xbb, 0x48, 0x3b, 0x66, 0xc9, 0xf2, 0x56, 0xca, 0x3a, 0x32, 0x5c, 0xed, 0x98, 0x2d, 0xa4, 0x94,
-	0xb1, 0xd0, 0xbb, 0x19, 0x46, 0x4c, 0x7d, 0x12, 0x69, 0xbe, 0xf7, 0x9a, 0xdc, 0x99, 0x7b, 0x9c,
-	0x9b, 0x5f, 0xee, 0xf1, 0xbf, 0x36, 0x60, 0x31, 0xad, 0x04, 0x86, 0x32, 0x70, 0x32, 0x9e, 0x52,
-	0x9a, 0xeb, 0xaf, 0xcb, 0x7e, 0xb5, 0xb5, 0xc2, 0x5d, 0xff, 0xb8, 0xfe, 0x2f, 0x5f, 0xae, 0x18,
-	0xff, 0xfe, 0xe5, 0x8a, 0xf1, 0x5f, 0x5f, 0xae, 0x18, 0x7f, 0xf3, 0xdf, 0x2b, 0x53, 0x27, 0x05,
-	0xf6, 0x5f, 0x90, 0xbf, 0xfd, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x98, 0x81, 0x56, 0x23, 0x07,
-	0x3d, 0x00, 0x00,
+	// 4394 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x6f, 0x24, 0x49,
+	0x56, 0xce, 0xfa, 0x74, 0xbd, 0x2a, 0x97, 0xcb, 0xd1, 0xee, 0x9e, 0xea, 0x9a, 0x6e, 0xb7, 0x27,
+	0x7b, 0x7a, 0xc6, 0xe3, 0x99, 0xb1, 0xbb, 0x6d, 0xf7, 0x0e, 0x34, 0x9a, 0x61, 0xab, 0xed, 0x9a,
+	0xb6, 0x69, 0xb7, 0xed, 0x4d, 0x57, 0xf7, 0xec, 0x0c, 0xd2, 0x9a, 0x74, 0x55, 0xb4, 0x9d, 0xeb,
+	0xaa, 0xcc, 0xda, 0xcc, 0x2c, 0xb7, 0xbd, 0x1c, 0x76, 0x59, 0x58, 0x56, 0x0b, 0xd2, 0x4a, 0x2c,
+	0x12, 0x5a, 0x21, 0xb8, 0x20, 0x24, 0x38, 0x00, 0x82, 0x03, 0x07, 0xc4, 0x81, 0x03, 0x1c, 0xe0,
+	0x80, 0x84, 0xc4, 0x1f, 0x80, 0x61, 0x4f, 0xfc, 0x05, 0x24, 0xb4, 0x8a, 0xaf, 0x8c, 0xc8, 0xcc,
+	0x28, 0xdb, 0xb3, 0xf6, 0x68, 0x2f, 0xd3, 0x95, 0x11, 0xef, 0x2b, 0xde, 0x8b, 0xf7, 0x5e, 0xc4,
+	0x7b, 0xe1, 0x81, 0x92, 0x3f, 0xe8, 0x2c, 0x0c, 0x7c, 0x2f, 0xf4, 0x50, 0x05, 0x87, 0x9d, 0x6e,
+	0x80, 0xfd, 0x63, 0xec, 0x0f, 0xf6, 0x1b, 0xd3, 0x07, 0xde, 0x81, 0x47, 0x27, 0x16, 0xc9, 0x2f,
+	0x06, 0xd3, 0xa8, 0x13, 0x98, 0x45, 0x7b, 0xe0, 0x2c, 0xf6, 0x8f, 0x3b, 0x9d, 0xc1, 0xfe, 0xe2,
+	0xd1, 0x31, 0x9f, 0x69, 0x44, 0x33, 0xf6, 0x30, 0x3c, 0x1c, 0xec, 0xd3, 0x7f, 0xf8, 0xdc, 0x6c,
+	0x34, 0x77, 0x8c, 0xfd, 0xc0, 0xf1, 0xdc, 0xc1, 0xbe, 0xf8, 0xc5, 0x21, 0x6e, 0x1d, 0x78, 0xde,
+	0x41, 0x0f, 0x33, 0x7c, 0xd7, 0xf5, 0x42, 0x3b, 0x74, 0x3c, 0x37, 0x60, 0xb3, 0xe6, 0x8f, 0x0c,
+	0xa8, 0x5a, 0x38, 0x18, 0x78, 0x6e, 0x80, 0xd7, 0xb1, 0xdd, 0xc5, 0x3e, 0xba, 0x0d, 0xd0, 0xe9,
+	0x0d, 0x83, 0x10, 0xfb, 0x7b, 0x4e, 0xb7, 0x6e, 0xcc, 0x1a, 0x73, 0x39, 0xab, 0xc4, 0x47, 0x36,
+	0xba, 0xe8, 0x75, 0x28, 0xf5, 0x71, 0x7f, 0x9f, 0xcd, 0x66, 0xe8, 0xec, 0x38, 0x1b, 0xd8, 0xe8,
+	0xa2, 0x06, 0x8c, 0xfb, 0xf8, 0xd8, 0x21, 0xec, 0xeb, 0xd9, 0x59, 0x63, 0x2e, 0x6b, 0x45, 0xdf,
+	0x04, 0xd1, 0xb7, 0x5f, 0x86, 0x7b, 0x21, 0xf6, 0xfb, 0xf5, 0x1c, 0x43, 0x24, 0x03, 0x6d, 0xec,
+	0xf7, 0x1f, 0x15, 0xbf, 0xf7, 0xf7, 0xf5, 0xec, 0xf2, 0xc2, 0x7d, 0xf3, 0x9f, 0xf3, 0x50, 0xb1,
+	0x6c, 0xf7, 0x00, 0x5b, 0xf8, 0x5b, 0x43, 0x1c, 0x84, 0xa8, 0x06, 0xd9, 0x23, 0x7c, 0x4a, 0xe5,
+	0xa8, 0x58, 0xe4, 0x27, 0x23, 0xe4, 0x1e, 0xe0, 0x3d, 0xec, 0x32, 0x09, 0x2a, 0x84, 0x90, 0x7b,
+	0x80, 0x5b, 0x6e, 0x17, 0x4d, 0x43, 0xbe, 0xe7, 0xf4, 0x9d, 0x90, 0xb3, 0x67, 0x1f, 0x31, 0xb9,
+	0x72, 0x09, 0xb9, 0x56, 0x01, 0x02, 0xcf, 0x0f, 0xf7, 0x3c, 0xbf, 0x8b, 0xfd, 0x7a, 0x7e, 0xd6,
+	0x98, 0xab, 0x2e, 0xbd, 0xb9, 0xa0, 0x5a, 0x6c, 0x41, 0x15, 0x68, 0x61, 0xd7, 0xf3, 0xc3, 0x6d,
+	0x02, 0x6b, 0x95, 0x02, 0xf1, 0x13, 0x7d, 0x0c, 0x65, 0x4a, 0x24, 0xb4, 0xfd, 0x03, 0x1c, 0xd6,
+	0x0b, 0x94, 0xca, 0xbd, 0x73, 0xa8, 0xb4, 0x29, 0xb0, 0x45, 0xd9, 0xb3, 0xdf, 0xc8, 0x84, 0x4a,
+	0x80, 0x7d, 0xc7, 0xee, 0x39, 0xdf, 0xb6, 0xf7, 0x7b, 0xb8, 0x5e, 0x9c, 0x35, 0xe6, 0xc6, 0xad,
+	0xd8, 0x18, 0x59, 0xff, 0x11, 0x3e, 0x0d, 0xf6, 0x3c, 0xb7, 0x77, 0x5a, 0x1f, 0xa7, 0x00, 0xe3,
+	0x64, 0x60, 0xdb, 0xed, 0x9d, 0x52, 0xeb, 0x79, 0x43, 0x37, 0x64, 0xb3, 0x25, 0x3a, 0x5b, 0xa2,
+	0x23, 0x74, 0xfa, 0x01, 0xd4, 0xfa, 0x8e, 0xbb, 0xd7, 0xf7, 0xba, 0x7b, 0x91, 0x42, 0x80, 0x28,
+	0xe4, 0x71, 0xf1, 0xf7, 0xa8, 0x05, 0x1e, 0x58, 0xd5, 0xbe, 0xe3, 0x3e, 0xf3, 0xba, 0x96, 0xd0,
+	0x0f, 0x41, 0xb1, 0x4f, 0xe2, 0x28, 0xe5, 0x24, 0x8a, 0x7d, 0xa2, 0xa2, 0x7c, 0x00, 0xd7, 0x08,
+	0x97, 0x8e, 0x8f, 0xed, 0x10, 0x4b, 0xac, 0x4a, 0x1c, 0x6b, 0xaa, 0xef, 0xb8, 0xab, 0x14, 0x24,
+	0x86, 0x68, 0x9f, 0xa4, 0x10, 0x27, 0x92, 0x88, 0xf6, 0x49, 0x1c, 0xd1, 0xfc, 0x00, 0x4a, 0x91,
+	0x5d, 0xd0, 0x38, 0xe4, 0xb6, 0xb6, 0xb7, 0x5a, 0xb5, 0x31, 0x04, 0x50, 0x68, 0xee, 0xae, 0xb6,
+	0xb6, 0xd6, 0x6a, 0x06, 0x2a, 0x43, 0x71, 0xad, 0xc5, 0x3e, 0x32, 0x8d, 0xe2, 0x8f, 0xf9, 0x7e,
+	0x7b, 0x0a, 0x20, 0x4d, 0x81, 0x8a, 0x90, 0x7d, 0xda, 0xfa, 0xb4, 0x36, 0x46, 0x80, 0x5f, 0xb4,
+	0xac, 0xdd, 0x8d, 0xed, 0xad, 0x9a, 0x41, 0xa8, 0xac, 0x5a, 0xad, 0x66, 0xbb, 0x55, 0xcb, 0x10,
+	0x88, 0x67, 0xdb, 0x6b, 0xb5, 0x2c, 0x2a, 0x41, 0xfe, 0x45, 0x73, 0xf3, 0x79, 0xab, 0x96, 0x8b,
+	0x88, 0xc9, 0x5d, 0xfc, 0x27, 0x06, 0x4c, 0x70, 0x73, 0x33, 0xdf, 0x42, 0x2b, 0x50, 0x38, 0xa4,
+	0xfe, 0x45, 0x77, 0x72, 0x79, 0xe9, 0x56, 0x62, 0x6f, 0xc4, 0x7c, 0xd0, 0xe2, 0xb0, 0xc8, 0x84,
+	0xec, 0xd1, 0x71, 0x50, 0xcf, 0xcc, 0x66, 0xe7, 0xca, 0x4b, 0xb5, 0x05, 0x16, 0x19, 0x16, 0x9e,
+	0xe2, 0xd3, 0x17, 0x76, 0x6f, 0x88, 0x2d, 0x32, 0x89, 0x10, 0xe4, 0xfa, 0x9e, 0x8f, 0xe9, 0x86,
+	0x1f, 0xb7, 0xe8, 0x6f, 0xe2, 0x05, 0xd4, 0xe6, 0x7c, 0xb3, 0xb3, 0x0f, 0x29, 0xde, 0xbf, 0x1b,
+	0x00, 0x3b, 0xc3, 0x70, 0xb4, 0x8b, 0x4d, 0x43, 0xfe, 0x98, 0x70, 0xe0, 0xee, 0xc5, 0x3e, 0xa8,
+	0x6f, 0x61, 0x3b, 0xc0, 0x91, 0x6f, 0x91, 0x0f, 0x34, 0x0b, 0xc5, 0x81, 0x8f, 0x8f, 0xf7, 0x8e,
+	0x8e, 0x29, 0xb7, 0x71, 0x69, 0xa7, 0x02, 0x19, 0x7f, 0x7a, 0x8c, 0xe6, 0xa1, 0xe2, 0x1c, 0xb8,
+	0x9e, 0x8f, 0xf7, 0x18, 0xd1, 0xbc, 0x0a, 0xb6, 0x64, 0x95, 0xd9, 0x24, 0x5d, 0x92, 0x02, 0xcb,
+	0x58, 0x15, 0xb4, 0xb0, 0x9b, 0x64, 0x4e, 0xae, 0xe7, 0xbb, 0x06, 0x94, 0xe9, 0x7a, 0x2e, 0xa5,
+	0xec, 0x25, 0xb9, 0x90, 0x0c, 0x45, 0x4b, 0x29, 0x3c, 0xb5, 0x34, 0x29, 0x82, 0x0b, 0x68, 0x0d,
+	0xf7, 0x70, 0x88, 0x2f, 0x13, 0xbc, 0x14, 0x55, 0x66, 0xb5, 0xaa, 0x94, 0xfc, 0xfe, 0xdc, 0x80,
+	0x6b, 0x31, 0x86, 0x97, 0x5a, 0x7a, 0x1d, 0x8a, 0x5d, 0x4a, 0x8c, 0xc9, 0x94, 0xb5, 0xc4, 0x27,
+	0x5a, 0x81, 0x71, 0x2e, 0x52, 0x50, 0xcf, 0xea, 0xb7, 0xa1, 0x94, 0xb2, 0xc8, 0xa4, 0x0c, 0xa4,
+	0x98, 0xff, 0x98, 0x81, 0x12, 0x57, 0xc6, 0xf6, 0x00, 0x35, 0x61, 0xc2, 0x67, 0x1f, 0x7b, 0x74,
+	0xcd, 0x5c, 0xc6, 0xc6, 0xe8, 0x38, 0xb9, 0x3e, 0x66, 0x55, 0x38, 0x0a, 0x1d, 0x46, 0xbf, 0x02,
+	0x65, 0x41, 0x62, 0x30, 0x0c, 0xb9, 0xa1, 0xea, 0x71, 0x02, 0x72, 0x6b, 0xaf, 0x8f, 0x59, 0xc0,
+	0xc1, 0x77, 0x86, 0x21, 0x6a, 0xc3, 0xb4, 0x40, 0x66, 0xeb, 0xe3, 0x62, 0x64, 0x29, 0x95, 0xd9,
+	0x38, 0x95, 0xb4, 0x39, 0xd7, 0xc7, 0x2c, 0xc4, 0xf1, 0x95, 0x49, 0xb4, 0x26, 0x45, 0x0a, 0x4f,
+	0x58, 0x7e, 0x49, 0x89, 0xd4, 0x3e, 0x71, 0x39, 0x11, 0xa1, 0xad, 0x65, 0x45, 0xb6, 0xf6, 0x89,
+	0x1b, 0xa9, 0xec, 0x71, 0x09, 0x8a, 0x7c, 0xd8, 0xfc, 0xb7, 0x0c, 0x80, 0xb0, 0xd8, 0xf6, 0x00,
+	0xad, 0x41, 0xd5, 0xe7, 0x5f, 0x31, 0xfd, 0xbd, 0xae, 0xd5, 0x1f, 0x37, 0xf4, 0x98, 0x35, 0x21,
+	0x90, 0x98, 0xb8, 0x1f, 0x41, 0x25, 0xa2, 0x22, 0x55, 0x78, 0x53, 0xa3, 0xc2, 0x88, 0x42, 0x59,
+	0x20, 0x10, 0x25, 0x7e, 0x02, 0xd7, 0x23, 0x7c, 0x8d, 0x16, 0xdf, 0x38, 0x43, 0x8b, 0x11, 0xc1,
+	0x6b, 0x82, 0x82, 0xaa, 0xc7, 0x27, 0x8a, 0x60, 0x52, 0x91, 0x37, 0x35, 0x8a, 0x64, 0x40, 0xaa,
+	0x26, 0x23, 0x09, 0x63, 0xaa, 0x04, 0x92, 0xf6, 0xd9, 0xb8, 0xf9, 0x97, 0x39, 0x28, 0xae, 0x7a,
+	0xfd, 0x81, 0xed, 0x93, 0x4d, 0x54, 0xf0, 0x71, 0x30, 0xec, 0x85, 0x54, 0x81, 0xd5, 0xa5, 0xbb,
+	0x71, 0x1e, 0x1c, 0x4c, 0xfc, 0x6b, 0x51, 0x50, 0x8b, 0xa3, 0x10, 0x64, 0x9e, 0xe5, 0x33, 0x17,
+	0x40, 0xe6, 0x39, 0x9e, 0xa3, 0x88, 0x80, 0x90, 0x95, 0x01, 0xa1, 0x01, 0x45, 0x7e, 0x60, 0x63,
+	0xc1, 0x7a, 0x7d, 0xcc, 0x12, 0x03, 0xe8, 0x1d, 0x98, 0x4c, 0xa6, 0xc2, 0x3c, 0x87, 0xa9, 0x76,
+	0xe2, 0x99, 0xf3, 0x2e, 0x54, 0x62, 0x19, 0xba, 0xc0, 0xe1, 0xca, 0x7d, 0x25, 0x2f, 0xdf, 0x10,
+	0x61, 0x9d, 0x1c, 0x2b, 0x2a, 0xeb, 0x63, 0x22, 0xb0, 0xdf, 0x11, 0x81, 0x7d, 0x5c, 0x4d, 0xb4,
+	0x44, 0xaf, 0x3c, 0xc6, 0xbf, 0xa9, 0x46, 0xad, 0xaf, 0x12, 0xe4, 0x08, 0x48, 0x86, 0x2f, 0xd3,
+	0x82, 0x89, 0x98, 0xca, 0x48, 0x8e, 0x6c, 0x7d, 0xed, 0x79, 0x73, 0x93, 0x25, 0xd4, 0x27, 0x34,
+	0x87, 0x5a, 0x35, 0x83, 0x24, 0xe8, 0xcd, 0xd6, 0xee, 0x6e, 0x2d, 0x83, 0x6e, 0x40, 0x69, 0x6b,
+	0xbb, 0xbd, 0xc7, 0xa0, 0xb2, 0x8d, 0xe2, 0x1f, 0xb3, 0x48, 0x22, 0xf3, 0xf3, 0xa7, 0x11, 0x4d,
+	0x9e, 0xa2, 0x95, 0xcc, 0x3c, 0xa6, 0x64, 0x66, 0x43, 0x64, 0xe6, 0x8c, 0xcc, 0xcc, 0x59, 0x84,
+	0x20, 0xbf, 0xd9, 0x6a, 0xee, 0xd2, 0x24, 0xcd, 0x48, 0x2f, 0xa7, 0xb3, 0xf5, 0xe3, 0x2a, 0x54,
+	0x98, 0x79, 0xf6, 0x86, 0x2e, 0x39, 0x4c, 0xfc, 0x95, 0x01, 0x20, 0x1d, 0x16, 0x2d, 0x42, 0xb1,
+	0xc3, 0x44, 0xa8, 0x1b, 0x34, 0x02, 0x5e, 0xd7, 0x5a, 0xdc, 0x12, 0x50, 0xe8, 0x01, 0x14, 0x83,
+	0x61, 0xa7, 0x83, 0x03, 0x91, 0xb9, 0x5f, 0x4b, 0x06, 0x61, 0x1e, 0x10, 0x2d, 0x01, 0x47, 0x50,
+	0x5e, 0xda, 0x4e, 0x6f, 0x48, 0xf3, 0xf8, 0xd9, 0x28, 0x1c, 0x4e, 0xc6, 0xd8, 0x3f, 0x33, 0xa0,
+	0xac, 0xb8, 0xc5, 0xcf, 0x99, 0x02, 0x6e, 0x41, 0x89, 0x0a, 0x83, 0xbb, 0x3c, 0x09, 0x8c, 0x5b,
+	0x72, 0x00, 0x7d, 0x05, 0x4a, 0xc2, 0x93, 0x44, 0x1e, 0xa8, 0xeb, 0xc9, 0x6e, 0x0f, 0x2c, 0x09,
+	0x2a, 0x85, 0x6c, 0xc3, 0x14, 0xd5, 0x53, 0x87, 0xdc, 0x3e, 0x84, 0x66, 0xd5, 0x63, 0xb9, 0x91,
+	0x38, 0x96, 0x37, 0x60, 0x7c, 0x70, 0x78, 0x1a, 0x38, 0x1d, 0xbb, 0xc7, 0xc5, 0x89, 0xbe, 0x25,
+	0xd5, 0x5d, 0x40, 0x2a, 0xd5, 0xcb, 0x28, 0x40, 0x12, 0xbd, 0x01, 0xe5, 0x75, 0x3b, 0x38, 0xe4,
+	0x42, 0xca, 0xf1, 0x15, 0x98, 0x20, 0xe3, 0x4f, 0x5f, 0x5c, 0x40, 0x7c, 0x81, 0xb5, 0x4c, 0x6f,
+	0x58, 0x02, 0xed, 0x52, 0x06, 0x42, 0x90, 0x3b, 0xb4, 0x83, 0x43, 0xaa, 0x8c, 0x09, 0x8b, 0xfe,
+	0x46, 0xef, 0x40, 0xad, 0xc3, 0xd6, 0xbf, 0x97, 0xb8, 0x77, 0x4d, 0xf2, 0x71, 0x2b, 0x25, 0x90,
+	0x0d, 0x15, 0xb6, 0xbc, 0xab, 0x96, 0x46, 0x6a, 0xaa, 0x01, 0x93, 0xbb, 0xae, 0x3d, 0x08, 0x0e,
+	0xbd, 0x30, 0xa1, 0xc5, 0x65, 0xf3, 0xef, 0x0c, 0xa8, 0xc9, 0xc9, 0x4b, 0xc9, 0xf0, 0x36, 0x4c,
+	0xfa, 0xb8, 0x6f, 0x3b, 0xae, 0xe3, 0x1e, 0xec, 0xed, 0x9f, 0x86, 0x38, 0xe0, 0x17, 0xd2, 0x6a,
+	0x34, 0xfc, 0x98, 0x8c, 0x12, 0x61, 0xf7, 0x7b, 0xde, 0x3e, 0x0f, 0xbb, 0xf4, 0x37, 0x7a, 0x23,
+	0x1e, 0x77, 0x4b, 0x22, 0xa0, 0x7d, 0x25, 0x0a, 0xbf, 0x52, 0xe6, 0x9f, 0x64, 0xa0, 0xf2, 0x89,
+	0x1d, 0x76, 0xc4, 0x9e, 0x40, 0x1b, 0x50, 0x8d, 0x02, 0x33, 0x1d, 0xe1, 0x72, 0x27, 0x8e, 0x10,
+	0x14, 0x47, 0xdc, 0x54, 0xc4, 0x11, 0x62, 0xa2, 0xa3, 0x0e, 0x50, 0x52, 0xb6, 0xdb, 0xc1, 0xbd,
+	0x88, 0x54, 0x66, 0x34, 0x29, 0x0a, 0xa8, 0x92, 0x52, 0x07, 0xd0, 0xd7, 0xa1, 0x36, 0xf0, 0xbd,
+	0x03, 0x1f, 0x07, 0x41, 0x44, 0x8c, 0x25, 0x65, 0x53, 0x43, 0x6c, 0x87, 0x83, 0x26, 0xce, 0x25,
+	0x2b, 0xeb, 0x63, 0xd6, 0xe4, 0x20, 0x3e, 0x27, 0x43, 0xe5, 0xa4, 0x3c, 0xc1, 0xb1, 0x58, 0xf9,
+	0x83, 0x2c, 0xa0, 0xf4, 0x32, 0xbf, 0xe8, 0xc1, 0xf7, 0x1e, 0x54, 0x83, 0xd0, 0xf6, 0x53, 0xbb,
+	0x78, 0x82, 0x8e, 0x46, 0xf9, 0xeb, 0x6d, 0x88, 0x24, 0xdb, 0x73, 0xbd, 0xd0, 0x79, 0x79, 0xca,
+	0xae, 0x1c, 0x56, 0x55, 0x0c, 0x6f, 0xd1, 0x51, 0xb4, 0x05, 0xc5, 0x97, 0x4e, 0x2f, 0xc4, 0x7e,
+	0x50, 0xcf, 0xcf, 0x66, 0xe7, 0xaa, 0x4b, 0xef, 0x9e, 0x67, 0x98, 0x85, 0x8f, 0x29, 0x7c, 0xfb,
+	0x74, 0xa0, 0x9e, 0x67, 0x39, 0x11, 0xf5, 0x60, 0x5e, 0xd0, 0xdf, 0x71, 0x4c, 0x18, 0x7f, 0x45,
+	0x88, 0xee, 0x39, 0x5d, 0x9a, 0x5d, 0xa3, 0x2c, 0xba, 0x62, 0x15, 0xe9, 0xc4, 0x46, 0x17, 0xdd,
+	0x85, 0xf1, 0x97, 0xbe, 0x7d, 0xd0, 0xc7, 0x6e, 0xc8, 0xee, 0xed, 0x12, 0x26, 0x9a, 0x30, 0x17,
+	0x00, 0xa4, 0x28, 0x24, 0x97, 0x6d, 0x6d, 0xef, 0x3c, 0x6f, 0xd7, 0xc6, 0x50, 0x05, 0xc6, 0xb7,
+	0xb6, 0xd7, 0x5a, 0x9b, 0x2d, 0x92, 0xed, 0x44, 0x16, 0x7b, 0x20, 0x9d, 0xae, 0x29, 0x0c, 0x11,
+	0xdb, 0x13, 0xaa, 0x5c, 0x46, 0xfc, 0x1a, 0x2d, 0xe4, 0x12, 0x24, 0x1e, 0x98, 0x77, 0x60, 0x5a,
+	0xb7, 0x35, 0x04, 0xc0, 0x8a, 0xf9, 0x2f, 0x19, 0x98, 0xe0, 0x8e, 0x70, 0x29, 0xcf, 0xbd, 0xa9,
+	0x48, 0xc5, 0x2f, 0x1c, 0x42, 0x49, 0x75, 0x28, 0x32, 0x07, 0xe9, 0xf2, 0x1b, 0xad, 0xf8, 0x24,
+	0xe1, 0x96, 0xed, 0x77, 0xdc, 0xe5, 0x66, 0x8f, 0xbe, 0xb5, 0x81, 0x30, 0xaf, 0x0d, 0x84, 0xe8,
+	0x3d, 0x98, 0x88, 0x1c, 0xce, 0x0e, 0xf8, 0x51, 0xa9, 0x24, 0x4d, 0x51, 0x11, 0x4e, 0x45, 0x26,
+	0x63, 0x36, 0x2b, 0x8e, 0xb0, 0x19, 0xba, 0x07, 0x05, 0x7c, 0x8c, 0xdd, 0x30, 0xa8, 0x97, 0x69,
+	0x6a, 0x9c, 0x10, 0x57, 0xa4, 0x16, 0x19, 0xb5, 0xf8, 0xa4, 0x34, 0xd5, 0x47, 0x30, 0x45, 0x6f,
+	0xb0, 0x4f, 0x7c, 0xdb, 0x55, 0x6f, 0xe1, 0xed, 0xf6, 0x26, 0x4f, 0x24, 0xe4, 0x27, 0xaa, 0x42,
+	0x66, 0x63, 0x8d, 0xeb, 0x27, 0xb3, 0xb1, 0x26, 0xf1, 0x7f, 0xdf, 0x00, 0xa4, 0x12, 0xb8, 0x94,
+	0x2d, 0x12, 0x5c, 0x84, 0x1c, 0x59, 0x29, 0xc7, 0x34, 0xe4, 0xb1, 0xef, 0x7b, 0x3e, 0x0b, 0x94,
+	0x16, 0xfb, 0x90, 0xd2, 0xbc, 0xcf, 0x85, 0xb1, 0xf0, 0xb1, 0x77, 0x14, 0x45, 0x00, 0x46, 0xd6,
+	0x48, 0x0b, 0xdf, 0x86, 0x6b, 0x31, 0xf0, 0xab, 0x49, 0xda, 0xdb, 0x30, 0x49, 0xa9, 0xae, 0x1e,
+	0xe2, 0xce, 0xd1, 0xc0, 0x73, 0xdc, 0x94, 0x04, 0xe8, 0x2e, 0x89, 0x5d, 0x22, 0x5d, 0x90, 0x25,
+	0xb2, 0x35, 0x57, 0xa2, 0xc1, 0x76, 0x7b, 0x53, 0x6e, 0xf5, 0x7d, 0xb8, 0x91, 0x20, 0x28, 0x56,
+	0xf6, 0xab, 0x50, 0xee, 0x44, 0x83, 0x01, 0x3f, 0x13, 0xde, 0x8e, 0x8b, 0x9b, 0x44, 0x55, 0x31,
+	0x24, 0x8f, 0xaf, 0xc3, 0x6b, 0x29, 0x1e, 0x57, 0xa1, 0x8e, 0x15, 0xf3, 0x3e, 0x5c, 0xa7, 0x94,
+	0x9f, 0x62, 0x3c, 0x68, 0xf6, 0x9c, 0xe3, 0xf3, 0xcd, 0x72, 0xca, 0xd7, 0xab, 0x60, 0x7c, 0xb9,
+	0xdb, 0x4a, 0xb2, 0x6e, 0x71, 0xd6, 0x6d, 0xa7, 0x8f, 0xdb, 0xde, 0xe6, 0x68, 0x69, 0x49, 0x22,
+	0x3f, 0xc2, 0xa7, 0x01, 0x3f, 0x10, 0xd2, 0xdf, 0x32, 0x7a, 0xfd, 0x8d, 0xc1, 0xd5, 0xa9, 0xd2,
+	0xf9, 0x92, 0x5d, 0x63, 0x06, 0xe0, 0x80, 0xf8, 0x20, 0xee, 0x92, 0x09, 0x56, 0x6d, 0x53, 0x46,
+	0x22, 0x81, 0x49, 0x16, 0xaa, 0x24, 0x05, 0xbe, 0xcd, 0x1d, 0x87, 0xfe, 0x27, 0x48, 0x9d, 0x94,
+	0xde, 0x82, 0x32, 0x9d, 0xd9, 0x0d, 0xed, 0x70, 0x18, 0x8c, 0xb2, 0xdc, 0xb2, 0xf9, 0x03, 0x83,
+	0x7b, 0x94, 0xa0, 0x73, 0xa9, 0x35, 0x3f, 0x80, 0x02, 0xbd, 0xf3, 0x89, 0xbb, 0xcb, 0x4d, 0xcd,
+	0xc6, 0x66, 0x12, 0x59, 0x1c, 0x50, 0x39, 0x27, 0x19, 0x50, 0x78, 0x46, 0x7b, 0x01, 0x8a, 0xb4,
+	0x39, 0x61, 0x39, 0xd7, 0xee, 0xb3, 0x82, 0x62, 0xc9, 0xa2, 0xbf, 0xe9, 0x11, 0x1f, 0x63, 0xff,
+	0xb9, 0xb5, 0xc9, 0xee, 0x14, 0x25, 0x2b, 0xfa, 0x26, 0x8a, 0xed, 0xf4, 0x1c, 0xec, 0x86, 0x74,
+	0x36, 0x47, 0x67, 0x95, 0x11, 0x74, 0x0f, 0x4a, 0x4e, 0xb0, 0x89, 0x6d, 0xdf, 0xe5, 0x45, 0x7b,
+	0x25, 0x30, 0xcb, 0x19, 0xb9, 0xc7, 0xbe, 0x01, 0x35, 0x26, 0x59, 0xb3, 0xdb, 0x55, 0xce, 0xef,
+	0x11, 0x7f, 0x23, 0xc1, 0x3f, 0x46, 0x3f, 0x73, 0x3e, 0xfd, 0xbf, 0x35, 0x60, 0x4a, 0x61, 0x70,
+	0x29, 0x13, 0xbc, 0x07, 0x05, 0xd6, 0x51, 0xe1, 0x47, 0xc1, 0xe9, 0x38, 0x16, 0x63, 0x63, 0x71,
+	0x18, 0xb4, 0x00, 0x45, 0xf6, 0x4b, 0x5c, 0xcc, 0xf4, 0xe0, 0x02, 0x48, 0x8a, 0xbc, 0x00, 0xd7,
+	0xf8, 0x1c, 0xee, 0x7b, 0x3a, 0x9f, 0xcb, 0xc5, 0x23, 0xc4, 0xf7, 0x0d, 0x98, 0x8e, 0x23, 0x5c,
+	0x6a, 0x95, 0x8a, 0xdc, 0x99, 0x2f, 0x24, 0xf7, 0xaf, 0x09, 0xb9, 0x9f, 0x0f, 0xba, 0xca, 0x91,
+	0x33, 0xb9, 0xe3, 0x54, 0xeb, 0x66, 0xe2, 0xd6, 0x95, 0xb4, 0x7e, 0x14, 0xad, 0x49, 0x10, 0xbb,
+	0xd4, 0x9a, 0x3e, 0xb8, 0xd0, 0x9a, 0x94, 0x23, 0x58, 0x6a, 0x71, 0x1b, 0x62, 0x1b, 0x6d, 0x3a,
+	0x41, 0x94, 0x71, 0xde, 0x85, 0x4a, 0xcf, 0x71, 0xb1, 0xed, 0xf3, 0xae, 0x90, 0xa1, 0xee, 0xc7,
+	0x87, 0x56, 0x6c, 0x52, 0x92, 0xfa, 0x6d, 0x03, 0x90, 0x4a, 0xeb, 0x17, 0x63, 0xad, 0x45, 0xa1,
+	0xe0, 0x1d, 0xdf, 0xeb, 0x7b, 0xe1, 0x79, 0xdb, 0x6c, 0xc5, 0xfc, 0x5d, 0x03, 0xae, 0x27, 0x30,
+	0x7e, 0x11, 0x92, 0xaf, 0x98, 0xb7, 0x60, 0x6a, 0x0d, 0x8b, 0x33, 0x5e, 0xaa, 0x1a, 0xb0, 0x0b,
+	0x48, 0x9d, 0xbd, 0x9a, 0x53, 0xcc, 0x2f, 0xc1, 0xd4, 0x33, 0xef, 0x98, 0x04, 0x72, 0x32, 0x2d,
+	0xc3, 0x14, 0x2b, 0x4f, 0x45, 0xfa, 0x8a, 0xbe, 0x65, 0xe8, 0xdd, 0x05, 0xa4, 0x62, 0x5e, 0x85,
+	0x38, 0xcb, 0xe6, 0x7f, 0x1b, 0x50, 0x69, 0xf6, 0x6c, 0xbf, 0x2f, 0x44, 0xf9, 0x08, 0x0a, 0xac,
+	0xd6, 0xc2, 0x0b, 0xa7, 0x6f, 0xc5, 0xe9, 0xa9, 0xb0, 0xec, 0xa3, 0xc9, 0x2a, 0x33, 0x1c, 0x8b,
+	0x2c, 0x85, 0xf7, 0x8a, 0xd7, 0x12, 0xbd, 0xe3, 0x35, 0xf4, 0x3e, 0xe4, 0x6d, 0x82, 0x42, 0xd3,
+	0x6b, 0x35, 0x59, 0x00, 0xa3, 0xd4, 0xc8, 0x95, 0xc8, 0x62, 0x50, 0xe6, 0x87, 0x50, 0x56, 0x38,
+	0xa0, 0x22, 0x64, 0x9f, 0xb4, 0xf8, 0x35, 0xa9, 0xb9, 0xda, 0xde, 0x78, 0xc1, 0x8a, 0x82, 0x55,
+	0x80, 0xb5, 0x56, 0xf4, 0x9d, 0x49, 0x15, 0xff, 0x96, 0x4d, 0x9b, 0xd3, 0xe1, 0x79, 0x4b, 0x95,
+	0xd0, 0x18, 0x25, 0x61, 0xe6, 0x22, 0x12, 0x4a, 0xab, 0xfe, 0x96, 0x01, 0x13, 0x5c, 0x35, 0x97,
+	0x4d, 0xcd, 0x94, 0xf2, 0x88, 0xd4, 0xac, 0x2c, 0xc3, 0xe2, 0x80, 0x52, 0x86, 0x7f, 0x32, 0xa0,
+	0xb6, 0xe6, 0xbd, 0x72, 0x0f, 0x7c, 0xbb, 0x1b, 0xf9, 0xe0, 0xc7, 0x09, 0x73, 0x2e, 0x24, 0x6a,
+	0xf7, 0x09, 0x78, 0x39, 0x90, 0x30, 0x6b, 0x5d, 0xd6, 0x52, 0x58, 0x7e, 0x17, 0x9f, 0xe6, 0x57,
+	0x61, 0x32, 0x81, 0x44, 0x0c, 0xf4, 0xa2, 0xb9, 0xb9, 0xb1, 0x46, 0x0c, 0x42, 0x2b, 0xb8, 0xad,
+	0xad, 0xe6, 0xe3, 0xcd, 0x16, 0xef, 0xb3, 0x36, 0xb7, 0x56, 0x5b, 0x9b, 0xd2, 0x50, 0x0f, 0xc5,
+	0x0a, 0x1e, 0x9a, 0x3d, 0x98, 0x52, 0x04, 0xba, 0x6c, 0xbb, 0x4b, 0x2f, 0xaf, 0xe4, 0x56, 0x87,
+	0x09, 0x7e, 0xca, 0x49, 0x3a, 0xfe, 0xff, 0x65, 0xa0, 0x2a, 0xa6, 0xbe, 0x1c, 0x29, 0xd0, 0x0d,
+	0x28, 0x74, 0xf7, 0x77, 0x9d, 0x6f, 0x8b, 0x4e, 0x2b, 0xff, 0x22, 0xe3, 0x3d, 0xc6, 0x87, 0xbd,
+	0x9f, 0xe0, 0x5f, 0xe8, 0x16, 0x7b, 0x5a, 0xb1, 0xe1, 0x76, 0xf1, 0x09, 0x3d, 0x0c, 0xe5, 0x2c,
+	0x39, 0x40, 0xcb, 0x94, 0xfc, 0x9d, 0x05, 0xbd, 0xeb, 0x2a, 0xef, 0x2e, 0xd0, 0x32, 0xd4, 0xc8,
+	0xef, 0xe6, 0x60, 0xd0, 0x73, 0x70, 0x97, 0x11, 0x20, 0xd7, 0xdc, 0x9c, 0x3c, 0xed, 0xa4, 0x00,
+	0xd0, 0x1d, 0x28, 0xd0, 0x2b, 0x60, 0x50, 0x1f, 0x27, 0x79, 0x55, 0x82, 0xf2, 0x61, 0xf4, 0x0e,
+	0x94, 0x99, 0xc4, 0x1b, 0xee, 0xf3, 0x00, 0xd3, 0x57, 0x08, 0x4a, 0x3d, 0x44, 0x9d, 0x8b, 0x9f,
+	0xb3, 0xe0, 0xfc, 0x73, 0xd6, 0x2d, 0x98, 0x6a, 0x0e, 0xc3, 0xc3, 0x96, 0x4b, 0x72, 0x5d, 0xca,
+	0x36, 0xb7, 0x01, 0x91, 0xd9, 0x35, 0x27, 0xd0, 0x4e, 0x73, 0x64, 0xad, 0x61, 0x1f, 0x9a, 0x5b,
+	0x70, 0x8d, 0xcc, 0x62, 0x37, 0x74, 0x3a, 0xca, 0xb9, 0x42, 0x9c, 0x5c, 0x8d, 0xc4, 0xc9, 0xd5,
+	0x0e, 0x82, 0x57, 0x9e, 0xdf, 0xe5, 0xb6, 0x8b, 0xbe, 0x25, 0xb7, 0x7f, 0x30, 0x98, 0x34, 0xcf,
+	0x83, 0xd8, 0xa9, 0xf3, 0x0b, 0xd2, 0x43, 0xbf, 0x0c, 0x45, 0x6f, 0x40, 0xdf, 0xec, 0xf0, 0x62,
+	0xde, 0x8d, 0x05, 0xf6, 0x0e, 0x68, 0x81, 0x13, 0xde, 0x66, 0xb3, 0x4a, 0xc1, 0x89, 0xc3, 0xa3,
+	0x45, 0xa8, 0x1e, 0xda, 0xc1, 0x21, 0xee, 0xee, 0x08, 0xe2, 0xb1, 0x52, 0xe7, 0x43, 0x2b, 0x31,
+	0x2d, 0x65, 0x7f, 0x20, 0x45, 0x7f, 0x82, 0xc3, 0x33, 0x44, 0x57, 0xcb, 0xe3, 0xd7, 0x05, 0x0a,
+	0xef, 0xea, 0x5d, 0x04, 0xeb, 0x87, 0x06, 0xdc, 0x16, 0x68, 0xab, 0x87, 0xb6, 0x7b, 0x80, 0x85,
+	0x30, 0x3f, 0xaf, 0xbe, 0xd2, 0x8b, 0xce, 0x5e, 0x70, 0xd1, 0x4f, 0xa1, 0x1e, 0x2d, 0x9a, 0x16,
+	0x56, 0xbc, 0x9e, 0xba, 0x88, 0x61, 0xc0, 0x1d, 0xbc, 0x64, 0xd1, 0xdf, 0x64, 0xcc, 0xf7, 0x7a,
+	0xd1, 0x9d, 0x86, 0xfc, 0x96, 0xc4, 0x36, 0xe1, 0xa6, 0x20, 0xc6, 0x2b, 0x1d, 0x71, 0x6a, 0xa9,
+	0x35, 0x9d, 0x49, 0x8d, 0xdb, 0x83, 0xd0, 0x38, 0x7b, 0x2b, 0x69, 0x51, 0xe2, 0x26, 0xa4, 0x5c,
+	0x0c, 0x1d, 0x97, 0x19, 0xe6, 0x01, 0x44, 0x66, 0xe5, 0xf8, 0x99, 0x9a, 0x27, 0x24, 0xb5, 0xf3,
+	0x7c, 0x0b, 0x90, 0xf9, 0xd4, 0x16, 0x18, 0xcd, 0x15, 0xc3, 0x4c, 0x24, 0x28, 0x51, 0xfb, 0x0e,
+	0xf6, 0xfb, 0x4e, 0x10, 0x28, 0x7d, 0x22, 0x9d, 0xba, 0xde, 0x82, 0xdc, 0x00, 0xf3, 0x5c, 0x5c,
+	0x5e, 0x42, 0xc2, 0x27, 0x14, 0x64, 0x3a, 0x2f, 0xd9, 0xf4, 0xe1, 0x8e, 0x60, 0xc3, 0x0c, 0xa2,
+	0xe5, 0x93, 0x14, 0x53, 0x54, 0xb2, 0x33, 0x23, 0x2a, 0xd9, 0xd9, 0x78, 0x25, 0x3b, 0x76, 0x3e,
+	0x54, 0x03, 0xd5, 0xd5, 0x9c, 0x0f, 0xdb, 0xcc, 0x00, 0x51, 0x7c, 0xbb, 0x1a, 0xaa, 0x7f, 0xc0,
+	0x03, 0xd5, 0x55, 0x65, 0x35, 0x4c, 0xd7, 0x2c, 0xba, 0x88, 0xe2, 0x13, 0x99, 0x50, 0x21, 0x46,
+	0xb2, 0xd4, 0x12, 0x7f, 0xce, 0x8a, 0x8d, 0xc9, 0x60, 0x7c, 0x04, 0xd3, 0xf1, 0x60, 0x7c, 0x29,
+	0xa1, 0xa6, 0x21, 0x1f, 0x7a, 0x47, 0x58, 0x24, 0x5a, 0xf6, 0x91, 0x52, 0x6b, 0x14, 0xa8, 0xaf,
+	0x46, 0xad, 0xdf, 0x94, 0x54, 0xa9, 0x03, 0x5e, 0x76, 0x05, 0x64, 0x3b, 0x8a, 0xab, 0x2c, 0xfb,
+	0x90, 0xbc, 0x3e, 0x81, 0x1b, 0xc9, 0xe0, 0x7b, 0x35, 0x8b, 0xd8, 0x63, 0xce, 0xa9, 0x0b, 0xcf,
+	0x57, 0xc3, 0xe0, 0x33, 0x19, 0x27, 0x95, 0xa0, 0x7b, 0x35, 0xb4, 0x7f, 0x1d, 0x1a, 0xba, 0x18,
+	0x7c, 0xa5, 0xbe, 0x18, 0x85, 0xe4, 0xab, 0xa1, 0xfa, 0x7d, 0x43, 0x92, 0x55, 0x77, 0xcd, 0x87,
+	0x5f, 0x84, 0xac, 0xc8, 0x75, 0xf7, 0xa3, 0xed, 0xb3, 0x18, 0x45, 0xcb, 0xac, 0x3e, 0x5a, 0x4a,
+	0x14, 0x0a, 0x28, 0xfc, 0x4f, 0x86, 0xfa, 0x2f, 0x73, 0xf7, 0x72, 0x66, 0x32, 0xef, 0x5c, 0x96,
+	0x19, 0x49, 0xcf, 0x11, 0x33, 0xfa, 0x91, 0x72, 0x15, 0x35, 0x49, 0x5d, 0x8d, 0xe9, 0x7e, 0x43,
+	0x26, 0x98, 0x54, 0x1e, 0xbb, 0x1a, 0x0e, 0x36, 0xcc, 0x8e, 0x4e, 0x61, 0x57, 0xc2, 0x62, 0xbe,
+	0x09, 0xa5, 0xe8, 0x22, 0xab, 0x3c, 0xa4, 0x2d, 0x43, 0x71, 0x6b, 0x7b, 0x77, 0xa7, 0xb9, 0x4a,
+	0xee, 0x69, 0xd3, 0x50, 0x5c, 0xdd, 0xb6, 0xac, 0xe7, 0x3b, 0x6d, 0x72, 0x51, 0x4b, 0xbc, 0xab,
+	0x59, 0x5e, 0xfa, 0x69, 0x16, 0x32, 0x4f, 0x5f, 0xa0, 0x4f, 0x21, 0xcf, 0xde, 0x75, 0x9d, 0xf1,
+	0xbc, 0xaf, 0x71, 0xd6, 0xd3, 0x35, 0xf3, 0xb5, 0xef, 0xfd, 0xe7, 0x4f, 0xff, 0x30, 0x33, 0x65,
+	0x56, 0x16, 0x8f, 0x97, 0x17, 0x8f, 0x8e, 0x17, 0x69, 0x92, 0x7d, 0x64, 0xcc, 0xa3, 0xaf, 0x41,
+	0x76, 0x67, 0x18, 0xa2, 0x91, 0xcf, 0xfe, 0x1a, 0xa3, 0x5f, 0xb3, 0x99, 0xd7, 0x29, 0xd1, 0x49,
+	0x13, 0x38, 0xd1, 0xc1, 0x30, 0x24, 0x24, 0xbf, 0x05, 0x65, 0xf5, 0x2d, 0xda, 0xb9, 0x6f, 0x01,
+	0x1b, 0xe7, 0xbf, 0x73, 0x33, 0x6f, 0x53, 0x56, 0xaf, 0x99, 0x88, 0xb3, 0x62, 0xaf, 0xe5, 0xd4,
+	0x55, 0xb4, 0x4f, 0x5c, 0x34, 0xf2, 0xa5, 0x60, 0x63, 0xf4, 0xd3, 0xb7, 0xd4, 0x2a, 0xc2, 0x13,
+	0x97, 0x90, 0xfc, 0x26, 0x7f, 0xe3, 0xd6, 0x09, 0xd1, 0x1d, 0xcd, 0x23, 0x25, 0xf5, 0xf1, 0x4d,
+	0x63, 0x76, 0x34, 0x00, 0x67, 0x72, 0x8b, 0x32, 0xb9, 0x61, 0x4e, 0x71, 0x26, 0x9d, 0x08, 0xe4,
+	0x91, 0x31, 0xbf, 0xd4, 0x81, 0x3c, 0x6d, 0x05, 0xa3, 0xcf, 0xc4, 0x8f, 0x86, 0xa6, 0xc9, 0x3e,
+	0xc2, 0xd0, 0xb1, 0x26, 0xb2, 0x39, 0x4d, 0x19, 0x55, 0xcd, 0x12, 0x61, 0x44, 0x1b, 0xc1, 0x8f,
+	0x8c, 0xf9, 0x39, 0xe3, 0xbe, 0xb1, 0xf4, 0xd7, 0x79, 0xc8, 0xd3, 0x96, 0x03, 0x3a, 0x02, 0x90,
+	0x2d, 0xcf, 0xe4, 0xea, 0x52, 0xdd, 0xd4, 0xe4, 0xea, 0xd2, 0xdd, 0x52, 0xb3, 0x41, 0x99, 0x4e,
+	0x9b, 0x93, 0x84, 0x29, 0xed, 0x64, 0x2c, 0xd2, 0xc6, 0x0d, 0xd1, 0xe3, 0x0f, 0x0d, 0xde, 0x7b,
+	0x61, 0x6e, 0x86, 0x74, 0xd4, 0x62, 0xed, 0xce, 0xe4, 0x76, 0xd0, 0x74, 0x38, 0xcd, 0x87, 0x94,
+	0xe1, 0xa2, 0x59, 0x93, 0x0c, 0x7d, 0x0a, 0xf1, 0xc8, 0x98, 0xff, 0xac, 0x6e, 0x5e, 0xe3, 0x5a,
+	0x4e, 0xcc, 0xa0, 0xef, 0x40, 0x35, 0xde, 0x98, 0x43, 0x77, 0x35, 0xbc, 0x92, 0x8d, 0xbe, 0xc6,
+	0x9b, 0x67, 0x03, 0x71, 0x99, 0x66, 0xa8, 0x4c, 0x9c, 0x39, 0xe3, 0x7c, 0x84, 0xf1, 0xc0, 0x26,
+	0x40, 0xdc, 0x06, 0xe8, 0x4f, 0x0d, 0xde, 0x5b, 0x95, 0x7d, 0x35, 0xa4, 0xa3, 0x9e, 0x6a, 0xdf,
+	0x35, 0xee, 0x9d, 0x03, 0xc5, 0x85, 0xf8, 0x90, 0x0a, 0xf1, 0x81, 0x39, 0x2d, 0x85, 0x08, 0x9d,
+	0x3e, 0x0e, 0x3d, 0x2e, 0xc5, 0x67, 0xb7, 0xcc, 0xd7, 0x62, 0xca, 0x89, 0xcd, 0x4a, 0x63, 0xb1,
+	0xfe, 0x97, 0xd6, 0x58, 0xb1, 0x16, 0x9b, 0xd6, 0x58, 0xf1, 0xe6, 0x99, 0xce, 0x58, 0xbc, 0xdb,
+	0xa5, 0x31, 0x56, 0x34, 0xb3, 0xf4, 0xbf, 0x39, 0x28, 0xae, 0xb2, 0xbf, 0x95, 0x41, 0x1e, 0x94,
+	0xa2, 0x8e, 0x10, 0x9a, 0xd1, 0x15, 0x9d, 0xe5, 0x55, 0xae, 0x71, 0x67, 0xe4, 0x3c, 0x17, 0xe8,
+	0x0d, 0x2a, 0xd0, 0xeb, 0xe6, 0x0d, 0xc2, 0x99, 0xff, 0x39, 0xce, 0x22, 0x2b, 0x4d, 0x2e, 0xda,
+	0xdd, 0x2e, 0x51, 0xc4, 0x6f, 0x42, 0x45, 0xed, 0xcf, 0xa0, 0x37, 0xb4, 0x85, 0x6e, 0xb5, 0xd9,
+	0xd3, 0x30, 0xcf, 0x02, 0xe1, 0x9c, 0xdf, 0xa4, 0x9c, 0x67, 0xcc, 0x9b, 0x1a, 0xce, 0x3e, 0x05,
+	0x8d, 0x31, 0x67, 0x8d, 0x14, 0x3d, 0xf3, 0x58, 0xc7, 0x46, 0xcf, 0x3c, 0xde, 0x87, 0x39, 0x93,
+	0xf9, 0x90, 0x82, 0x12, 0xe6, 0x01, 0x80, 0xec, 0x74, 0x20, 0xad, 0x2e, 0x95, 0x0b, 0x6b, 0x32,
+	0x38, 0xa4, 0x9b, 0x24, 0xa6, 0x49, 0xd9, 0xf2, 0x7d, 0x97, 0x60, 0xdb, 0x73, 0x82, 0x90, 0x39,
+	0xe6, 0x44, 0xac, 0x4f, 0x81, 0xb4, 0xeb, 0x89, 0xb7, 0x3d, 0x1a, 0x77, 0xcf, 0x84, 0xe1, 0xdc,
+	0xef, 0x51, 0xee, 0x77, 0xcc, 0x86, 0x86, 0xfb, 0x80, 0xc1, 0x92, 0xcd, 0xf6, 0xff, 0x05, 0x28,
+	0x3f, 0xb3, 0x1d, 0x37, 0xc4, 0xae, 0xed, 0x76, 0x30, 0xda, 0x87, 0x3c, 0xcd, 0xdd, 0xc9, 0x40,
+	0xac, 0x96, 0xe5, 0x93, 0x81, 0x38, 0x56, 0x97, 0x36, 0x67, 0x29, 0xe3, 0x86, 0x79, 0x9d, 0x30,
+	0xee, 0x4b, 0xd2, 0x8b, 0xac, 0xa2, 0x6d, 0xcc, 0xa3, 0x97, 0x50, 0xe0, 0xfd, 0xe8, 0x04, 0xa1,
+	0x58, 0x51, 0xad, 0x71, 0x4b, 0x3f, 0xa9, 0xdb, 0xcb, 0x2a, 0x9b, 0x80, 0xc2, 0x11, 0x3e, 0xc7,
+	0x00, 0xb2, 0xbd, 0x92, 0xb4, 0x68, 0xaa, 0x2d, 0xd3, 0x98, 0x1d, 0x0d, 0xa0, 0xd3, 0xa9, 0xca,
+	0xb3, 0x1b, 0xc1, 0x12, 0xbe, 0xdf, 0x80, 0xdc, 0xba, 0x1d, 0x1c, 0xa2, 0x44, 0xee, 0x55, 0x1e,
+	0x84, 0x36, 0x1a, 0xba, 0x29, 0xce, 0xe5, 0x0e, 0xe5, 0x72, 0x93, 0x85, 0x32, 0x95, 0x0b, 0x7d,
+	0x20, 0x69, 0xcc, 0xa3, 0x2e, 0x14, 0xd8, 0x6b, 0xd0, 0xa4, 0xfe, 0x62, 0x4f, 0x4b, 0x93, 0xfa,
+	0x8b, 0x3f, 0x20, 0x3d, 0x9f, 0xcb, 0x00, 0xc6, 0xc5, 0x1b, 0x4b, 0x94, 0x78, 0x99, 0x92, 0x78,
+	0x98, 0xd9, 0x98, 0x19, 0x35, 0xcd, 0x79, 0xdd, 0xa5, 0xbc, 0x6e, 0x9b, 0xf5, 0x94, 0xad, 0x38,
+	0xe4, 0x23, 0x63, 0xfe, 0xbe, 0x81, 0xbe, 0x03, 0x20, 0xfb, 0x4f, 0x29, 0x0f, 0x4c, 0xf6, 0xb4,
+	0x52, 0x1e, 0x98, 0x6a, 0x5d, 0x99, 0x0b, 0x94, 0xef, 0x9c, 0x79, 0x37, 0xc9, 0x37, 0xf4, 0x6d,
+	0x37, 0x78, 0x89, 0xfd, 0xf7, 0x59, 0xf1, 0x3b, 0x38, 0x74, 0x06, 0x64, 0xc9, 0x3e, 0x94, 0xa2,
+	0xf6, 0x40, 0x32, 0xda, 0x26, 0x1b, 0x19, 0xc9, 0x68, 0x9b, 0xea, 0x2b, 0xc4, 0xc3, 0x4e, 0x6c,
+	0xb7, 0x08, 0x50, 0xe2, 0x80, 0x7f, 0x51, 0x83, 0x1c, 0x39, 0x90, 0x93, 0xc3, 0x89, 0x2c, 0xf6,
+	0x24, 0x57, 0x9f, 0xaa, 0x57, 0x27, 0x57, 0x9f, 0xae, 0x13, 0xc5, 0x0f, 0x27, 0xe4, 0xb2, 0xb6,
+	0xc8, 0xaa, 0x28, 0x64, 0xa5, 0x1e, 0x94, 0x95, 0x22, 0x10, 0xd2, 0x10, 0x8b, 0xd7, 0xbf, 0x93,
+	0xe9, 0x4e, 0x53, 0x41, 0x32, 0x5f, 0xa7, 0xfc, 0xae, 0xb3, 0x74, 0x47, 0xf9, 0x75, 0x19, 0x04,
+	0x61, 0xc8, 0x57, 0xc7, 0xfd, 0x5e, 0xb3, 0xba, 0xb8, 0xef, 0xcf, 0x8e, 0x06, 0x18, 0xb9, 0x3a,
+	0xe9, 0xf8, 0xaf, 0xa0, 0xa2, 0x16, 0x7e, 0x90, 0x46, 0xf8, 0x44, 0x85, 0x3e, 0x99, 0x47, 0x74,
+	0x75, 0xa3, 0x78, 0x64, 0xa3, 0x2c, 0x6d, 0x05, 0x8c, 0x30, 0xee, 0x41, 0x91, 0x17, 0x80, 0x74,
+	0x2a, 0x8d, 0x17, 0xf1, 0x75, 0x2a, 0x4d, 0x54, 0x8f, 0xe2, 0xa7, 0x67, 0xca, 0x91, 0x5c, 0x44,
+	0x45, 0xae, 0xe6, 0xdc, 0x9e, 0xe0, 0x70, 0x14, 0x37, 0x59, 0xb4, 0x1d, 0xc5, 0x4d, 0xa9, 0x0f,
+	0x8c, 0xe2, 0x76, 0x80, 0x43, 0x1e, 0x0f, 0xc4, 0xe5, 0x1a, 0x8d, 0x20, 0xa6, 0xe6, 0x47, 0xf3,
+	0x2c, 0x10, 0xdd, 0xe5, 0x46, 0x32, 0x14, 0xc9, 0xf1, 0x04, 0x40, 0x16, 0xa3, 0x92, 0x27, 0x56,
+	0x6d, 0x9f, 0x20, 0x79, 0x62, 0xd5, 0xd7, 0xb3, 0xe2, 0xb1, 0x4f, 0xf2, 0x65, 0x77, 0x2b, 0xc2,
+	0xf9, 0xc7, 0x06, 0xa0, 0x74, 0xb9, 0x0a, 0xbd, 0xab, 0xa7, 0xae, 0xed, 0x39, 0x34, 0xde, 0xbb,
+	0x18, 0xb0, 0x2e, 0x9d, 0x49, 0x91, 0x3a, 0x14, 0x7a, 0xf0, 0x8a, 0x08, 0xf5, 0x5d, 0x03, 0x26,
+	0x62, 0x25, 0x2e, 0xf4, 0xd6, 0x08, 0x9b, 0x26, 0x1a, 0x0f, 0x8d, 0xb7, 0xcf, 0x85, 0xd3, 0x1d,
+	0xe5, 0x95, 0x1d, 0x20, 0xee, 0x34, 0xbf, 0x63, 0x40, 0x35, 0x5e, 0x09, 0x43, 0x23, 0x68, 0xa7,
+	0xfa, 0x15, 0x8d, 0xb9, 0xf3, 0x01, 0xcf, 0x36, 0x8f, 0xbc, 0xce, 0xf4, 0xa0, 0xc8, 0x4b, 0x66,
+	0xba, 0x8d, 0x1f, 0x6f, 0x70, 0xe8, 0x36, 0x7e, 0xa2, 0xde, 0xa6, 0xd9, 0xf8, 0xbe, 0xd7, 0xc3,
+	0x8a, 0x9b, 0xf1, 0x4a, 0xda, 0x28, 0x6e, 0x67, 0xbb, 0x59, 0xa2, 0x0c, 0x37, 0x8a, 0x9b, 0x74,
+	0x33, 0x51, 0x30, 0x43, 0x23, 0x88, 0x9d, 0xe3, 0x66, 0xc9, 0x7a, 0x9b, 0xc6, 0xcd, 0x28, 0x43,
+	0xc5, 0xcd, 0x64, 0x21, 0x4b, 0xe7, 0x66, 0xa9, 0x5e, 0x8c, 0xce, 0xcd, 0xd2, 0xb5, 0x30, 0x8d,
+	0x1d, 0x29, 0xdf, 0x98, 0x9b, 0x5d, 0xd3, 0x94, 0xba, 0xd0, 0x7b, 0x23, 0x94, 0xa8, 0xed, 0xec,
+	0x34, 0xde, 0xbf, 0x20, 0xf4, 0xc8, 0x3d, 0xce, 0xd4, 0x2f, 0xf6, 0xf8, 0x1f, 0x19, 0x30, 0xad,
+	0xab, 0x8e, 0xa1, 0x11, 0x7c, 0x46, 0x34, 0x82, 0x1a, 0x0b, 0x17, 0x05, 0x3f, 0x5b, 0x5b, 0xd1,
+	0xae, 0x7f, 0x5c, 0xfb, 0xd7, 0xcf, 0x67, 0x8c, 0xff, 0xf8, 0x7c, 0xc6, 0xf8, 0xaf, 0xcf, 0x67,
+	0x8c, 0x9f, 0xfc, 0xcf, 0xcc, 0xd8, 0x7e, 0x81, 0xfe, 0x0f, 0x18, 0x96, 0x7f, 0x16, 0x00, 0x00,
+	0xff, 0xff, 0xe6, 0x88, 0xc4, 0x9e, 0x27, 0x42, 0x00, 0x00,
 }
 
 // Reference imports to suppress errors if they are not otherwise used.
diff --git a/api/etcdserverpb/rpc.proto b/api/etcdserverpb/rpc.proto
index b9a6f33..29bca1f 100644
--- a/api/etcdserverpb/rpc.proto
+++ b/api/etcdserverpb/rpc.proto
@@ -4,6 +4,7 @@
 import "gogoproto/gogo.proto";
 import "etcd/api/mvccpb/kv.proto";
 import "etcd/api/authpb/auth.proto";
+import "etcd/api/versionpb/version.proto";
 
 // for grpc-gateway
 import "google/api/annotations.proto";
@@ -388,6 +389,8 @@
 }
 
 message ResponseHeader {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // cluster_id is the ID of the cluster which sent the response.
   uint64 cluster_id = 1;
   // member_id is the ID of the member which sent the response.
@@ -402,17 +405,21 @@
 }
 
 message RangeRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   enum SortOrder {
-	NONE = 0; // default, no sorting
-	ASCEND = 1; // lowest target value first
-	DESCEND = 2; // highest target value first
+    option (versionpb.etcd_version_enum) = "3.0";
+    NONE = 0; // default, no sorting
+    ASCEND = 1; // lowest target value first
+    DESCEND = 2; // highest target value first
   }
   enum SortTarget {
-	KEY = 0;
-	VERSION = 1;
-	CREATE = 2;
-	MOD = 3;
-	VALUE = 4;
+    option (versionpb.etcd_version_enum) = "3.0";
+    KEY = 0;
+    VERSION = 1;
+    CREATE = 2;
+    MOD = 3;
+    VALUE = 4;
   }
 
   // key is the first key for the range. If range_end is not given, the request only looks up key.
@@ -453,22 +460,24 @@
 
   // min_mod_revision is the lower bound for returned key mod revisions; all keys with
   // lesser mod revisions will be filtered away.
-  int64 min_mod_revision = 10;
+  int64 min_mod_revision = 10 [(versionpb.etcd_version_field)="3.1"];
 
   // max_mod_revision is the upper bound for returned key mod revisions; all keys with
   // greater mod revisions will be filtered away.
-  int64 max_mod_revision = 11;
+  int64 max_mod_revision = 11 [(versionpb.etcd_version_field)="3.1"];
 
   // min_create_revision is the lower bound for returned key create revisions; all keys with
   // lesser create revisions will be filtered away.
-  int64 min_create_revision = 12;
+  int64 min_create_revision = 12 [(versionpb.etcd_version_field)="3.1"];
 
   // max_create_revision is the upper bound for returned key create revisions; all keys with
   // greater create revisions will be filtered away.
-  int64 max_create_revision = 13;
+  int64 max_create_revision = 13 [(versionpb.etcd_version_field)="3.1"];
 }
 
 message RangeResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // kvs is the list of key-value pairs matched by the range request.
   // kvs is empty when count is requested.
@@ -480,6 +489,8 @@
 }
 
 message PutRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // key is the key, in bytes, to put into the key-value store.
   bytes key = 1;
   // value is the value, in bytes, to associate with the key in the key-value store.
@@ -490,24 +501,28 @@
 
   // If prev_kv is set, etcd gets the previous key-value pair before changing it.
   // The previous key-value pair will be returned in the put response.
-  bool prev_kv = 4;
+  bool prev_kv = 4 [(versionpb.etcd_version_field)="3.1"];
 
   // If ignore_value is set, etcd updates the key using its current value.
   // Returns an error if the key does not exist.
-  bool ignore_value = 5;
+  bool ignore_value = 5 [(versionpb.etcd_version_field)="3.2"];
 
   // If ignore_lease is set, etcd updates the key using its current lease.
   // Returns an error if the key does not exist.
-  bool ignore_lease = 6;
+  bool ignore_lease = 6 [(versionpb.etcd_version_field)="3.2"];
 }
 
 message PutResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // if prev_kv is set in the request, the previous key-value pair will be returned.
-  mvccpb.KeyValue prev_kv = 2;
+  mvccpb.KeyValue prev_kv = 2 [(versionpb.etcd_version_field)="3.1"];
 }
 
 message DeleteRangeRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // key is the first key to delete in the range.
   bytes key = 1;
   // range_end is the key following the last key to delete for the range [key, range_end).
@@ -519,50 +534,61 @@
 
   // If prev_kv is set, etcd gets the previous key-value pairs before deleting it.
   // The previous key-value pairs will be returned in the delete response.
-  bool prev_kv = 3;
+  bool prev_kv = 3 [(versionpb.etcd_version_field)="3.1"];
 }
 
 message DeleteRangeResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // deleted is the number of keys deleted by the delete range request.
   int64 deleted = 2;
   // if prev_kv is set in the request, the previous key-value pairs will be returned.
-  repeated mvccpb.KeyValue prev_kvs = 3;
+  repeated mvccpb.KeyValue prev_kvs = 3 [(versionpb.etcd_version_field)="3.1"];
 }
 
 message RequestOp {
+  option (versionpb.etcd_version_msg) = "3.0";
   // request is a union of request types accepted by a transaction.
   oneof request {
     RangeRequest request_range = 1;
     PutRequest request_put = 2;
     DeleteRangeRequest request_delete_range = 3;
-    TxnRequest request_txn = 4;
+    TxnRequest request_txn = 4 [(versionpb.etcd_version_field)="3.3"];
   }
 }
 
 message ResponseOp {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // response is a union of response types returned by a transaction.
   oneof response {
     RangeResponse response_range = 1;
     PutResponse response_put = 2;
     DeleteRangeResponse response_delete_range = 3;
-    TxnResponse response_txn = 4;
+    TxnResponse response_txn = 4 [(versionpb.etcd_version_field)="3.3"];
   }
 }
 
 message Compare {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   enum CompareResult {
+    option (versionpb.etcd_version_enum) = "3.0";
+
     EQUAL = 0;
     GREATER = 1;
     LESS = 2;
-    NOT_EQUAL = 3;
+    NOT_EQUAL = 3 [(versionpb.etcd_version_enum_value)="3.1"];
   }
   enum CompareTarget {
+    option (versionpb.etcd_version_enum) = "3.0";
+
     VERSION = 0;
     CREATE = 1;
     MOD = 2;
     VALUE = 3;
-    LEASE = 4;
+    LEASE = 4 [(versionpb.etcd_version_enum_value)="3.3"];
   }
   // result is logical comparison operation for this comparison.
   CompareResult result = 1;
@@ -580,13 +606,13 @@
     // value is the value of the given key, in bytes.
     bytes value = 7;
     // lease is the lease id of the given key.
-    int64 lease = 8;
+    int64 lease = 8 [(versionpb.etcd_version_field)="3.3"];
     // leave room for more target_union field tags, jump to 64
   }
 
   // range_end compares the given target to all keys in the range [key, range_end).
   // See RangeRequest for more details on key ranges.
-  bytes range_end = 64;
+  bytes range_end = 64 [(versionpb.etcd_version_field)="3.3"];
   // TODO: fill out with most of the rest of RangeRequest fields when needed.
 }
 
@@ -606,6 +632,8 @@
 // true.
 // 3. A list of database operations called f op. Like t op, but executed if guard evaluates to false.
 message TxnRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // compare is a list of predicates representing a conjunction of terms.
   // If the comparisons succeed, then the success requests will be processed in order,
   // and the response will contain their respective responses in order.
@@ -619,6 +647,8 @@
 }
 
 message TxnResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // succeeded is set to true if the compare evaluated to true or false otherwise.
   bool succeeded = 2;
@@ -630,6 +660,8 @@
 // CompactionRequest compacts the key-value store up to a given revision. All superseded keys
 // with a revision less than the compaction revision will be removed.
 message CompactionRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // revision is the key-value store revision for the compaction operation.
   int64 revision = 1;
   // physical is set so the RPC will wait until the compaction is physically
@@ -639,18 +671,24 @@
 }
 
 message CompactionResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message HashRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message HashKVRequest {
+  option (versionpb.etcd_version_msg) = "3.3";
   // revision is the key-value store revision for the hash operation.
   int64 revision = 1;
 }
 
 message HashKVResponse {
+  option (versionpb.etcd_version_msg) = "3.3";
+
   ResponseHeader header = 1;
   // hash is the hash value computed from the responding member's MVCC keys up to a given revision.
   uint32 hash = 2;
@@ -659,15 +697,20 @@
 }
 
 message HashResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // hash is the hash value computed from the responding member's KV's backend.
   uint32 hash = 2;
 }
 
 message SnapshotRequest {
+  option (versionpb.etcd_version_msg) = "3.3";
 }
 
 message SnapshotResponse {
+  option (versionpb.etcd_version_msg) = "3.3";
+
   // header has the current key-value store information. The first header in the snapshot
   // stream indicates the point in time of the snapshot.
   ResponseHeader header = 1;
@@ -681,19 +724,22 @@
   // local version of server that created the snapshot.
   // In cluster with binaries with different version, each cluster can return different result.
   // Informs which etcd server version should be used when restoring the snapshot.
-  string version = 4;
+  string version = 4 [(versionpb.etcd_version_field)="3.6"];
 }
 
 message WatchRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
   // request_union is a request to either create a new watcher or cancel an existing watcher.
   oneof request_union {
     WatchCreateRequest create_request = 1;
     WatchCancelRequest cancel_request = 2;
-    WatchProgressRequest progress_request = 3;
+    WatchProgressRequest progress_request = 3 [(versionpb.etcd_version_field)="3.4"];
   }
 }
 
 message WatchCreateRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // key is the key to register for watching.
   bytes key = 1;
 
@@ -714,6 +760,8 @@
   bool progress_notify = 4;
 
   enum FilterType {
+    option (versionpb.etcd_version_enum) = "3.1";
+
     // filter out put event.
     NOPUT = 0;
     // filter out delete event.
@@ -721,34 +769,38 @@
   }
 
   // filters filter the events at server side before it sends back to the watcher.
-  repeated FilterType filters = 5;
+  repeated FilterType filters = 5 [(versionpb.etcd_version_field)="3.1"];
 
   // If prev_kv is set, created watcher gets the previous KV before the event happens.
   // If the previous KV is already compacted, nothing will be returned.
-  bool prev_kv = 6;
+  bool prev_kv = 6 [(versionpb.etcd_version_field)="3.1"];
 
   // If watch_id is provided and non-zero, it will be assigned to this watcher.
   // Since creating a watcher in etcd is not a synchronous operation,
   // this can be used ensure that ordering is correct when creating multiple
   // watchers on the same stream. Creating a watcher with an ID already in
   // use on the stream will cause an error to be returned.
-  int64 watch_id = 7;
+  int64 watch_id = 7 [(versionpb.etcd_version_field)="3.4"];
 
   // fragment enables splitting large revisions into multiple watch responses.
-  bool fragment = 8;
+  bool fragment = 8 [(versionpb.etcd_version_field)="3.4"];
 }
 
 message WatchCancelRequest {
+  option (versionpb.etcd_version_msg) = "3.1";
   // watch_id is the watcher id to cancel so that no more events are transmitted.
-  int64 watch_id = 1;
+  int64 watch_id = 1 [(versionpb.etcd_version_field)="3.1"];
 }
 
 // Requests the a watch stream progress status be sent in the watch response stream as soon as
 // possible.
 message WatchProgressRequest {
+  option (versionpb.etcd_version_msg) = "3.4";
 }
 
 message WatchResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // watch_id is the ID of the watcher that corresponds to the response.
   int64 watch_id = 2;
@@ -774,15 +826,17 @@
   int64 compact_revision = 5;
 
   // cancel_reason indicates the reason for canceling the watcher.
-  string cancel_reason = 6;
+  string cancel_reason = 6 [(versionpb.etcd_version_field)="3.4"];
 
   // framgment is true if large watch response was split over multiple responses.
-  bool fragment = 7;
+  bool fragment = 7 [(versionpb.etcd_version_field)="3.4"];
 
   repeated mvccpb.Event events = 11;
 }
 
 message LeaseGrantRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // TTL is the advisory time-to-live in seconds. Expired lease will return -1.
   int64 TTL = 1;
   // ID is the requested ID for the lease. If ID is set to 0, the lessor chooses an ID.
@@ -790,6 +844,8 @@
 }
 
 message LeaseGrantResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // ID is the lease ID for the granted lease.
   int64 ID = 2;
@@ -799,15 +855,21 @@
 }
 
 message LeaseRevokeRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // ID is the lease ID to revoke. When the ID is revoked, all associated keys will be deleted.
   int64 ID = 1;
 }
 
 message LeaseRevokeResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message LeaseCheckpoint {
+  option (versionpb.etcd_version_msg) = "3.4";
+
     // ID is the lease ID to checkpoint.
   int64 ID = 1;
 
@@ -816,19 +878,26 @@
 }
 
 message LeaseCheckpointRequest {
+  option (versionpb.etcd_version_msg) = "3.4";
+
   repeated LeaseCheckpoint checkpoints = 1;
 }
 
 message LeaseCheckpointResponse {
+  option (versionpb.etcd_version_msg) = "3.4";
+
   ResponseHeader header = 1;
 }
 
 message LeaseKeepAliveRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
   // ID is the lease ID for the lease to keep alive.
   int64 ID = 1;
 }
 
 message LeaseKeepAliveResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // ID is the lease ID from the keep alive request.
   int64 ID = 2;
@@ -837,6 +906,7 @@
 }
 
 message LeaseTimeToLiveRequest {
+  option (versionpb.etcd_version_msg) = "3.1";
   // ID is the lease ID for the lease.
   int64 ID = 1;
   // keys is true to query all the keys attached to this lease.
@@ -844,6 +914,8 @@
 }
 
 message LeaseTimeToLiveResponse {
+  option (versionpb.etcd_version_msg) = "3.1";
+
   ResponseHeader header = 1;
   // ID is the lease ID from the keep alive request.
   int64 ID = 2;
@@ -856,19 +928,26 @@
 }
 
 message LeaseLeasesRequest {
+  option (versionpb.etcd_version_msg) = "3.3";
 }
 
 message LeaseStatus {
+  option (versionpb.etcd_version_msg) = "3.3";
+
   int64 ID = 1;
   // TODO: int64 TTL = 2;
 }
 
 message LeaseLeasesResponse {
+  option (versionpb.etcd_version_msg) = "3.3";
+
   ResponseHeader header = 1;
   repeated LeaseStatus leases = 2;
 }
 
 message Member {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // ID is the member ID for this member.
   uint64 ID = 1;
   // name is the human-readable name of the member. If the member is not started, the name will be an empty string.
@@ -878,17 +957,21 @@
   // clientURLs is the list of URLs the member exposes to clients for communication. If the member is not started, clientURLs will be empty.
   repeated string clientURLs = 4;
   // isLearner indicates if the member is raft learner.
-  bool isLearner = 5;
+  bool isLearner = 5 [(versionpb.etcd_version_field)="3.4"];
 }
 
 message MemberAddRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // peerURLs is the list of URLs the added member will use to communicate with the cluster.
   repeated string peerURLs = 1;
   // isLearner indicates if the added member is raft learner.
-  bool isLearner = 2;
+  bool isLearner = 2 [(versionpb.etcd_version_field)="3.4"];
 }
 
 message MemberAddResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // member is the member information for the added member.
   Member member = 2;
@@ -897,17 +980,22 @@
 }
 
 message MemberRemoveRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
   // ID is the member ID of the member to remove.
   uint64 ID = 1;
 }
 
 message MemberRemoveResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // members is a list of all members after removing the member.
   repeated Member members = 2;
 }
 
 message MemberUpdateRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // ID is the member ID of the member to update.
   uint64 ID = 1;
   // peerURLs is the new list of URLs the member will use to communicate with the cluster.
@@ -915,59 +1003,80 @@
 }
 
 message MemberUpdateResponse{
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // members is a list of all members after updating the member.
-  repeated Member members = 2;
+  repeated Member members = 2 [(versionpb.etcd_version_field)="3.1"];
 }
 
 message MemberListRequest {
-  bool linearizable = 1;
+  option (versionpb.etcd_version_msg) = "3.0";
+
+  bool linearizable = 1 [(versionpb.etcd_version_field)="3.5"];
 }
 
 message MemberListResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // members is a list of all members associated with the cluster.
   repeated Member members = 2;
 }
 
 message MemberPromoteRequest {
+  option (versionpb.etcd_version_msg) = "3.4";
   // ID is the member ID of the member to promote.
   uint64 ID = 1;
 }
 
 message MemberPromoteResponse {
+  option (versionpb.etcd_version_msg) = "3.4";
+
   ResponseHeader header = 1;
   // members is a list of all members after promoting the member.
   repeated Member members = 2;
 }
 
 message DefragmentRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message DefragmentResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message MoveLeaderRequest {
+  option (versionpb.etcd_version_msg) = "3.3";
   // targetID is the node ID for the new leader.
   uint64 targetID = 1;
 }
 
 message MoveLeaderResponse {
+  option (versionpb.etcd_version_msg) = "3.3";
+
   ResponseHeader header = 1;
 }
 
 enum AlarmType {
+  option (versionpb.etcd_version_enum) = "3.0";
+
 	NONE = 0; // default, used to query if any alarm is active
 	NOSPACE = 1; // space quota is exhausted
-	CORRUPT = 2; // kv store corruption detected
+	CORRUPT = 2 [(versionpb.etcd_version_enum_value)="3.3"]; // kv store corruption detected
 }
 
 message AlarmRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   enum AlarmAction {
-	GET = 0;
-	ACTIVATE = 1;
-	DEACTIVATE = 2;
+    option (versionpb.etcd_version_enum) = "3.0";
+
+    GET = 0;
+    ACTIVATE = 1;
+    DEACTIVATE = 2;
   }
   // action is the kind of alarm request to issue. The action
   // may GET alarm statuses, ACTIVATE an alarm, or DEACTIVATE a
@@ -981,6 +1090,7 @@
 }
 
 message AlarmMember {
+  option (versionpb.etcd_version_msg) = "3.0";
   // memberID is the ID of the member associated with the raised alarm.
   uint64 memberID = 1;
   // alarm is the type of alarm which has been raised.
@@ -988,13 +1098,19 @@
 }
 
 message AlarmResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // alarms is a list of alarms associated with the alarm request.
   repeated AlarmMember alarms = 2;
 }
 
 message DowngradeRequest {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   enum DowngradeAction {
+    option (versionpb.etcd_version_enum) = "3.5";
+
     VALIDATE = 0;
     ENABLE = 1;
     CANCEL = 2;
@@ -1009,15 +1125,20 @@
 }
 
 message DowngradeResponse {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   ResponseHeader header = 1;
   // version is the current cluster version.
   string version = 2;
 }
 
 message StatusRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message StatusResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // version is the cluster protocol version used by the responding member.
   string version = 2;
@@ -1030,55 +1151,69 @@
   // raftTerm is the current raft term of the responding member.
   uint64 raftTerm = 6;
   // raftAppliedIndex is the current raft applied index of the responding member.
-  uint64 raftAppliedIndex = 7;
+  uint64 raftAppliedIndex = 7 [(versionpb.etcd_version_field)="3.4"];
   // errors contains alarm/health information and status.
-  repeated string errors = 8;
+  repeated string errors = 8 [(versionpb.etcd_version_field)="3.4"];
   // dbSizeInUse is the size of the backend database logically in use, in bytes, of the responding member.
-  int64 dbSizeInUse = 9;
+  int64 dbSizeInUse = 9 [(versionpb.etcd_version_field)="3.4"];
   // isLearner indicates if the member is raft learner.
-  bool isLearner = 10;
+  bool isLearner = 10 [(versionpb.etcd_version_field)="3.4"];
 }
 
 message AuthEnableRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message AuthDisableRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message AuthStatusRequest {
+  option (versionpb.etcd_version_msg) = "3.5";
 }
 
 message AuthenticateRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string name = 1;
   string password = 2;
 }
 
 message AuthUserAddRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string name = 1;
   string password = 2;
-  authpb.UserAddOptions options = 3;
-  string hashedPassword = 4;
+  authpb.UserAddOptions options = 3 [(versionpb.etcd_version_field)="3.4"];
+  string hashedPassword = 4 [(versionpb.etcd_version_field)="3.5"];
 }
 
 message AuthUserGetRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string name = 1;
 }
 
 message AuthUserDeleteRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
   // name is the name of the user to delete.
   string name = 1;
 }
 
 message AuthUserChangePasswordRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // name is the name of the user whose password is being changed.
   string name = 1;
   // password is the new password for the user. Note that this field will be removed in the API layer.
   string password = 2;
   // hashedPassword is the new password for the user. Note that this field will be initialized in the API layer.
-  string hashedPassword = 3;
+  string hashedPassword = 3 [(versionpb.etcd_version_field)="3.5"];
 }
 
 message AuthUserGrantRoleRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // user is the name of the user which should be granted a given role.
   string user = 1;
   // role is the name of the role to grant to the user.
@@ -1086,30 +1221,42 @@
 }
 
 message AuthUserRevokeRoleRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string name = 1;
   string role = 2;
 }
 
 message AuthRoleAddRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // name is the name of the role to add to the authentication system.
   string name = 1;
 }
 
 message AuthRoleGetRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string role = 1;
 }
 
 message AuthUserListRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message AuthRoleListRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
 }
 
 message AuthRoleDeleteRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string role = 1;
 }
 
 message AuthRoleGrantPermissionRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   // name is the name of the role which will be granted the permission.
   string name = 1;
   // perm is the permission to grant to the role.
@@ -1117,20 +1264,28 @@
 }
 
 message AuthRoleRevokePermissionRequest {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   string role = 1;
   bytes key = 2;
   bytes range_end = 3;
 }
 
 message AuthEnableResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthDisableResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthStatusResponse {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   ResponseHeader header = 1;
   bool enabled = 2;
   // authRevision is the current revision of auth store
@@ -1138,67 +1293,93 @@
 }
 
 message AuthenticateResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
   // token is an authorized token that can be used in succeeding RPCs
   string token = 2;
 }
 
 message AuthUserAddResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthUserGetResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 
   repeated string roles = 2;
 }
 
 message AuthUserDeleteResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthUserChangePasswordResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthUserGrantRoleResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthUserRevokeRoleResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthRoleAddResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthRoleGetResponse {
-  ResponseHeader header = 1;
+  ResponseHeader header = 1 [(versionpb.etcd_version_field)="3.0"];
 
-  repeated authpb.Permission perm = 2;
+  repeated authpb.Permission perm = 2 [(versionpb.etcd_version_field)="3.0"];
 }
 
 message AuthRoleListResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 
   repeated string roles = 2;
 }
 
 message AuthUserListResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 
   repeated string users = 2;
 }
 
 message AuthRoleDeleteResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthRoleGrantPermissionResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
 
 message AuthRoleRevokePermissionResponse {
+  option (versionpb.etcd_version_msg) = "3.0";
+
   ResponseHeader header = 1;
 }
diff --git a/api/membershippb/membership.pb.go b/api/membershippb/membership.pb.go
index cf0d428..386185f 100644
--- a/api/membershippb/membership.pb.go
+++ b/api/membershippb/membership.pb.go
@@ -11,6 +11,7 @@
 
 	_ "github.com/gogo/protobuf/gogoproto"
 	proto "github.com/golang/protobuf/proto"
+	_ "go.etcd.io/etcd/api/v3/versionpb"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -286,30 +287,33 @@
 func init() { proto.RegisterFile("membership.proto", fileDescriptor_949fe0d019050ef5) }
 
 var fileDescriptor_949fe0d019050ef5 = []byte{
-	// 367 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0x4e, 0xf2, 0x40,
-	0x14, 0x85, 0x99, 0x42, 0xf8, 0xdb, 0xcb, 0x1f, 0xc4, 0x09, 0x89, 0x8d, 0x68, 0x25, 0x5d, 0xb1,
-	0x30, 0x98, 0xe8, 0x13, 0xa0, 0xb0, 0x20, 0x81, 0xcd, 0x18, 0xdd, 0x92, 0x56, 0x2e, 0xd8, 0xa4,
-	0x74, 0xea, 0xcc, 0x54, 0xd7, 0xbe, 0x85, 0x4f, 0xe0, 0xb3, 0xb0, 0xf4, 0x11, 0x14, 0x5f, 0xc4,
-	0x74, 0x5a, 0x4a, 0x49, 0xdc, 0xb8, 0xbb, 0x3d, 0xbd, 0xf7, 0x9c, 0xf3, 0x35, 0x85, 0xd6, 0x0a,
-	0x57, 0x3e, 0x0a, 0xf9, 0x18, 0xc4, 0xfd, 0x58, 0x70, 0xc5, 0xe9, 0xff, 0x9d, 0x12, 0xfb, 0xc7,
-	0xed, 0x25, 0x5f, 0x72, 0xfd, 0xe2, 0x22, 0x9d, 0xb2, 0x1d, 0x77, 0x02, 0x4d, 0xe6, 0x2d, 0xd4,
-	0x40, 0x29, 0x11, 0xf8, 0x89, 0x42, 0x49, 0x3b, 0x60, 0xc5, 0x88, 0x62, 0x96, 0x88, 0x50, 0xda,
-	0xa4, 0x5b, 0xed, 0x59, 0xcc, 0x4c, 0x85, 0x3b, 0x11, 0x4a, 0x7a, 0x0a, 0x10, 0xc8, 0x59, 0x88,
-	0x9e, 0x88, 0x50, 0xd8, 0x46, 0x97, 0xf4, 0x4c, 0x66, 0x05, 0x72, 0x92, 0x09, 0xee, 0x00, 0xa0,
-	0xe4, 0x44, 0xa1, 0x16, 0x79, 0x2b, 0xb4, 0x49, 0x97, 0xf4, 0x2c, 0xa6, 0x67, 0x7a, 0x06, 0x8d,
-	0x87, 0x30, 0xc0, 0x48, 0x65, 0xfe, 0x86, 0xf6, 0x87, 0x4c, 0x4a, 0x13, 0xdc, 0x77, 0x02, 0xf5,
-	0xa9, 0xee, 0x4d, 0x9b, 0x60, 0x8c, 0x87, 0xfa, 0xba, 0xc6, 0x8c, 0xf1, 0x90, 0x8e, 0xe0, 0x40,
-	0x78, 0x0b, 0x35, 0xf3, 0x8a, 0x08, 0xdd, 0xa0, 0x71, 0x79, 0xd2, 0x2f, 0x93, 0xf6, 0xf7, 0x81,
-	0x58, 0x53, 0xec, 0x03, 0x8e, 0xe0, 0x30, 0x5b, 0x2f, 0x1b, 0x55, 0xb5, 0x91, 0xbd, 0x6f, 0x54,
-	0x32, 0xc9, 0xbf, 0xee, 0x4e, 0x71, 0xcf, 0xc1, 0xbe, 0x09, 0x13, 0xa9, 0x50, 0xdc, 0xa3, 0x90,
-	0x01, 0x8f, 0x6e, 0x51, 0x31, 0x7c, 0x4a, 0x50, 0x2a, 0xda, 0x82, 0xea, 0x33, 0x8a, 0x1c, 0x3c,
-	0x1d, 0xdd, 0x57, 0x02, 0x9d, 0x7c, 0x7d, 0x5a, 0x38, 0x95, 0x2e, 0x3a, 0x60, 0xe5, 0xa5, 0x0a,
-	0x64, 0x33, 0x13, 0x34, 0xf8, 0x2f, 0x8d, 0x8d, 0x3f, 0x37, 0x1e, 0xc1, 0xd1, 0x90, 0xbf, 0x44,
-	0x4b, 0xe1, 0xcd, 0x71, 0x1c, 0x2d, 0x78, 0x29, 0xde, 0x86, 0x7f, 0x18, 0x79, 0x7e, 0x88, 0x73,
-	0x1d, 0x6e, 0xb2, 0xed, 0xe3, 0x16, 0xc5, 0x28, 0x50, 0xae, 0xdb, 0xeb, 0x2f, 0xa7, 0xb2, 0xde,
-	0x38, 0xe4, 0x63, 0xe3, 0x90, 0xcf, 0x8d, 0x43, 0xde, 0xbe, 0x9d, 0x8a, 0x5f, 0xd7, 0xff, 0xd3,
-	0xd5, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x93, 0x7d, 0x0b, 0x87, 0x02, 0x00, 0x00,
+	// 401 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xcd, 0xae, 0xd2, 0x40,
+	0x14, 0xbe, 0xd3, 0xde, 0xdc, 0xdb, 0x9e, 0x6b, 0x10, 0x27, 0x24, 0x36, 0xa0, 0xb5, 0x61, 0xc5,
+	0xaa, 0x24, 0x12, 0x36, 0xee, 0x54, 0x58, 0x60, 0xc4, 0xc5, 0x18, 0xdc, 0x92, 0x29, 0x1c, 0xb0,
+	0x49, 0x69, 0xeb, 0xcc, 0x14, 0xf7, 0x2e, 0x7d, 0x02, 0xdf, 0xc2, 0x95, 0xef, 0xc0, 0xd2, 0x47,
+	0x50, 0x7c, 0x11, 0xd3, 0x99, 0x42, 0x4b, 0x74, 0x75, 0x77, 0xa7, 0x5f, 0xcf, 0xf9, 0xfe, 0x5a,
+	0x68, 0xef, 0x70, 0x17, 0xa1, 0x90, 0x1f, 0xe3, 0x3c, 0xcc, 0x45, 0xa6, 0x32, 0xfa, 0xa0, 0x46,
+	0xf2, 0xa8, 0xdb, 0xd9, 0x66, 0xdb, 0x4c, 0xbf, 0x18, 0x96, 0x93, 0xd9, 0xe9, 0x06, 0xa8, 0x56,
+	0xeb, 0x21, 0xcf, 0xe3, 0xe1, 0x1e, 0x85, 0x8c, 0xb3, 0x34, 0x8f, 0x4e, 0x93, 0xd9, 0xe8, 0x2f,
+	0xa0, 0xc5, 0xf8, 0x46, 0xbd, 0x54, 0x4a, 0xc4, 0x51, 0xa1, 0x50, 0xd2, 0x1e, 0xb8, 0x39, 0xa2,
+	0x58, 0x16, 0x22, 0x91, 0x1e, 0x09, 0xec, 0x81, 0xcb, 0x9c, 0x12, 0x58, 0x88, 0x44, 0xd2, 0xa7,
+	0x00, 0xb1, 0x5c, 0x26, 0xc8, 0x45, 0x8a, 0xc2, 0xb3, 0x02, 0x32, 0x70, 0x98, 0x1b, 0xcb, 0xb7,
+	0x06, 0x78, 0x71, 0xfb, 0xe5, 0x87, 0x67, 0x8f, 0xc2, 0x71, 0xff, 0x0d, 0x40, 0x83, 0x92, 0xc2,
+	0x75, 0xca, 0x77, 0xe8, 0x91, 0x80, 0x0c, 0x5c, 0xa6, 0x67, 0xfa, 0x0c, 0xee, 0x56, 0x49, 0x8c,
+	0xa9, 0x32, 0x42, 0x96, 0x16, 0x02, 0x03, 0x95, 0x52, 0x35, 0xd7, 0x77, 0x02, 0x37, 0x73, 0x9d,
+	0x95, 0xb6, 0xc0, 0x9a, 0x4d, 0x34, 0xcd, 0x35, 0xb3, 0x66, 0x13, 0x3a, 0x85, 0x87, 0x82, 0x6f,
+	0xd4, 0x92, 0x9f, 0xb5, 0xb4, 0xa7, 0xbb, 0xe7, 0x4f, 0xc2, 0x66, 0x3b, 0xe1, 0x65, 0x44, 0xd6,
+	0x12, 0x97, 0x91, 0xa7, 0xf0, 0xc8, 0xac, 0x37, 0x89, 0x6c, 0x4d, 0xe4, 0x5d, 0x12, 0x35, 0x48,
+	0xaa, 0x2f, 0x52, 0x23, 0xb5, 0xe3, 0x31, 0x78, 0xaf, 0x93, 0x42, 0x2a, 0x14, 0x1f, 0x4c, 0xd9,
+	0xef, 0x51, 0x31, 0xfc, 0x54, 0xa0, 0x54, 0xb4, 0x0d, 0xf6, 0x1e, 0x45, 0x55, 0x45, 0x39, 0xd6,
+	0x67, 0x5f, 0x09, 0xf4, 0xaa, 0xbb, 0xf9, 0x99, 0xbb, 0x71, 0xda, 0x03, 0xb7, 0xb2, 0x79, 0x2e,
+	0xc1, 0x31, 0x80, 0xae, 0xe2, 0x3f, 0x19, 0xac, 0xfb, 0x67, 0x78, 0x07, 0x8f, 0x27, 0xd9, 0xe7,
+	0x74, 0x2b, 0xf8, 0x1a, 0x67, 0xe9, 0x26, 0x6b, 0xf8, 0xf0, 0xe0, 0x16, 0x53, 0x1e, 0x25, 0xb8,
+	0xd6, 0x2e, 0x1c, 0x76, 0x7a, 0x3c, 0x85, 0xb3, 0xfe, 0x0d, 0xf7, 0xaa, 0x73, 0xf8, 0xed, 0x5f,
+	0x1d, 0x8e, 0x3e, 0xf9, 0x79, 0xf4, 0xc9, 0xaf, 0xa3, 0x4f, 0xbe, 0xfd, 0xf1, 0xaf, 0xa2, 0x1b,
+	0xfd, 0x17, 0x8e, 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xa3, 0xbd, 0xee, 0xdf, 0x02, 0x00,
+	0x00,
 }
 
 func (m *RaftAttributes) Marshal() (dAtA []byte, err error) {
diff --git a/api/membershippb/membership.proto b/api/membershippb/membership.proto
index e63e9ec..cb7254f 100644
--- a/api/membershippb/membership.proto
+++ b/api/membershippb/membership.proto
@@ -2,6 +2,7 @@
 package membershippb;
 
 import "gogoproto/gogo.proto";
+import "etcd/api/versionpb/version.proto";
 
 option (gogoproto.marshaler_all) = true;
 option (gogoproto.sizer_all) = true;
@@ -10,6 +11,8 @@
 
 // RaftAttributes represents the raft related attributes of an etcd member.
 message RaftAttributes {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   // peerURLs is the list of peers in the raft cluster.
   repeated string peer_urls = 1;
   // isLearner indicates if the member is raft learner.
@@ -18,26 +21,36 @@
 
 // Attributes represents all the non-raft related attributes of an etcd member.
 message Attributes {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   string name = 1;
   repeated string client_urls = 2;
 }
 
 message Member {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   uint64 ID = 1;
   RaftAttributes raft_attributes = 2;
   Attributes member_attributes = 3;
 }
 
 message ClusterVersionSetRequest {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   string ver = 1;
 }
 
 message ClusterMemberAttrSetRequest {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   uint64 member_ID = 1;
   Attributes member_attributes = 2;
 }
 
 message DowngradeInfoSetRequest {
+  option (versionpb.etcd_version_msg) = "3.5";
+
   bool enabled = 1;
   string ver = 2;
 }
\ No newline at end of file
diff --git a/api/versionpb/version.pb.go b/api/versionpb/version.pb.go
new file mode 100644
index 0000000..8e5ce7e
--- /dev/null
+++ b/api/versionpb/version.pb.go
@@ -0,0 +1,90 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: version.proto
+
+package versionpb
+
+import (
+	fmt "fmt"
+	math "math"
+
+	_ "github.com/gogo/protobuf/gogoproto"
+	protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
+	proto "github.com/golang/protobuf/proto"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+var E_EtcdVersionMsg = &proto.ExtensionDesc{
+	ExtendedType:  (*protobuf.MessageOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         50000,
+	Name:          "versionpb.etcd_version_msg",
+	Tag:           "bytes,50000,opt,name=etcd_version_msg",
+	Filename:      "version.proto",
+}
+
+var E_EtcdVersionField = &proto.ExtensionDesc{
+	ExtendedType:  (*protobuf.FieldOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         50001,
+	Name:          "versionpb.etcd_version_field",
+	Tag:           "bytes,50001,opt,name=etcd_version_field",
+	Filename:      "version.proto",
+}
+
+var E_EtcdVersionEnum = &proto.ExtensionDesc{
+	ExtendedType:  (*protobuf.EnumOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         50002,
+	Name:          "versionpb.etcd_version_enum",
+	Tag:           "bytes,50002,opt,name=etcd_version_enum",
+	Filename:      "version.proto",
+}
+
+var E_EtcdVersionEnumValue = &proto.ExtensionDesc{
+	ExtendedType:  (*protobuf.EnumValueOptions)(nil),
+	ExtensionType: (*string)(nil),
+	Field:         50003,
+	Name:          "versionpb.etcd_version_enum_value",
+	Tag:           "bytes,50003,opt,name=etcd_version_enum_value",
+	Filename:      "version.proto",
+}
+
+func init() {
+	proto.RegisterExtension(E_EtcdVersionMsg)
+	proto.RegisterExtension(E_EtcdVersionField)
+	proto.RegisterExtension(E_EtcdVersionEnum)
+	proto.RegisterExtension(E_EtcdVersionEnumValue)
+}
+
+func init() { proto.RegisterFile("version.proto", fileDescriptor_7d2c07d79758f814) }
+
+var fileDescriptor_7d2c07d79758f814 = []byte{
+	// 261 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4b, 0x2d, 0x2a,
+	0xce, 0xcc, 0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x72, 0x0b, 0x92, 0xa4,
+	0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xa2, 0xfa, 0x20, 0x16, 0x44, 0x81, 0x94, 0x42, 0x7a, 0x7e,
+	0x7e, 0x7a, 0x4e, 0xaa, 0x3e, 0x98, 0x97, 0x54, 0x9a, 0xa6, 0x9f, 0x92, 0x5a, 0x9c, 0x5c, 0x94,
+	0x59, 0x50, 0x92, 0x5f, 0x04, 0x51, 0x61, 0xe5, 0xc7, 0x25, 0x90, 0x5a, 0x92, 0x9c, 0x12, 0x0f,
+	0x35, 0x29, 0x3e, 0xb7, 0x38, 0x5d, 0x48, 0x5e, 0x0f, 0xa2, 0x4d, 0x0f, 0xa6, 0x4d, 0xcf, 0x37,
+	0xb5, 0xb8, 0x38, 0x31, 0x3d, 0xd5, 0xbf, 0xa0, 0x24, 0x33, 0x3f, 0xaf, 0x58, 0xe2, 0x42, 0x1b,
+	0xb3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x1f, 0x48, 0x6b, 0x18, 0x44, 0xa7, 0x6f, 0x71, 0x7a, 0x07,
+	0x23, 0xa3, 0x55, 0x00, 0x97, 0x10, 0x8a, 0x79, 0x69, 0x99, 0xa9, 0x39, 0x29, 0x42, 0xb2, 0x18,
+	0x26, 0xba, 0x81, 0xc4, 0x61, 0xe6, 0x5d, 0x84, 0x9a, 0x27, 0x80, 0x64, 0x1e, 0x58, 0x01, 0xc8,
+	0x44, 0x5f, 0x2e, 0x41, 0x14, 0x13, 0x53, 0xf3, 0x4a, 0x73, 0x85, 0x64, 0x30, 0x0c, 0x74, 0xcd,
+	0x2b, 0xcd, 0x85, 0x99, 0x77, 0x09, 0x6a, 0x1e, 0x3f, 0x92, 0x79, 0x20, 0x79, 0x90, 0x71, 0xb1,
+	0x5c, 0xe2, 0x18, 0xc6, 0xc5, 0x97, 0x25, 0xe6, 0x94, 0xa6, 0x0a, 0x29, 0x62, 0x35, 0x34, 0x0c,
+	0x24, 0x07, 0x33, 0xf9, 0x32, 0xd4, 0x64, 0x11, 0x34, 0x93, 0xc1, 0x8a, 0x3a, 0x18, 0x19, 0x9d,
+	0x04, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x19, 0x8f,
+	0xe5, 0x18, 0x92, 0xd8, 0xc0, 0xa6, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x77, 0x44, 0xe2,
+	0xa4, 0xbc, 0x01, 0x00, 0x00,
+}
diff --git a/api/versionpb/version.proto b/api/versionpb/version.proto
new file mode 100644
index 0000000..27cfb5d
--- /dev/null
+++ b/api/versionpb/version.proto
@@ -0,0 +1,28 @@
+syntax = "proto3";
+package versionpb;
+
+import "gogoproto/gogo.proto";
+import "google/protobuf/descriptor.proto";
+
+option (gogoproto.marshaler_all) = true;
+option (gogoproto.unmarshaler_all) = true;
+
+// Indicates etcd version that introduced the message, used to determine minimal etcd version required to interpret wal that includes this message.
+extend google.protobuf.MessageOptions {
+  optional string etcd_version_msg = 50000;
+}
+
+// Indicates etcd version that introduced the field, used to determine minimal etcd version required to interpret wal that sets this field.
+extend google.protobuf.FieldOptions {
+  optional string etcd_version_field = 50001;
+}
+
+// Indicates etcd version that introduced the enum, used to determine minimal etcd version required to interpret wal that uses this enum.
+extend google.protobuf.EnumOptions {
+  optional string etcd_version_enum = 50002;
+}
+
+// Indicates etcd version that introduced the enum value, used to determine minimal etcd version required to interpret wal that sets this enum value.
+extend google.protobuf.EnumValueOptions {
+  optional string etcd_version_enum_value = 50003;
+}
diff --git a/bill-of-materials.json b/bill-of-materials.json
index b06c373..5d60d2c 100644
--- a/bill-of-materials.json
+++ b/bill-of-materials.json
@@ -117,15 +117,6 @@
 		]
 	},
 	{
-		"project": "github.com/form3tech-oss/jwt-go",
-		"licenses": [
-			{
-				"type": "MIT License",
-				"confidence": 0.9891304347826086
-			}
-		]
-	},
-	{
 		"project": "github.com/getsentry/raven-go",
 		"licenses": [
 			{
@@ -144,6 +135,15 @@
 		]
 	},
 	{
+		"project": "github.com/golang-jwt/jwt",
+		"licenses": [
+			{
+				"type": "MIT License",
+				"confidence": 0.9891304347826086
+			}
+		]
+	},
+	{
 		"project": "github.com/golang/groupcache/lru",
 		"licenses": [
 			{
diff --git a/contrib/mixin/mixin.libsonnet b/contrib/mixin/mixin.libsonnet
index 74336cf..e35be02 100644
--- a/contrib/mixin/mixin.libsonnet
+++ b/contrib/mixin/mixin.libsonnet
@@ -15,6 +15,8 @@
     // 1 : On Dashboard Load  (Will refresh Dashboards variables when dashboard are loaded)
     // 2 : On Time Range Change (Will refresh Dashboards variables when time range will be changed)
     dashboard_var_refresh: 2,
+    // clusterLabel is used to identify a cluster.
+    clusterLabel: 'job',
   },
 
   prometheusAlerts+:: {
@@ -39,7 +41,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": members are down ({{ $value }}).',
+              description: 'etcd cluster "{{ $labels.%s }}": members are down ({{ $value }}).' % $._config.clusterLabel,
               summary: 'etcd cluster members are down.',
             },
           },
@@ -53,7 +55,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": insufficient members ({{ $value }}).',
+              description: 'etcd cluster "{{ $labels.%s }}": insufficient members ({{ $value }}).' % $._config.clusterLabel,
               summary: 'etcd cluster has insufficient number of members.',
             },
           },
@@ -67,7 +69,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": member {{ $labels.instance }} has no leader.',
+              description: 'etcd cluster "{{ $labels.%s }}": member {{ $labels.instance }} has no leader.' % $._config.clusterLabel,
               summary: 'etcd cluster has no leader.',
             },
           },
@@ -81,7 +83,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": {{ $value }} leader changes within the last 15 minutes. Frequent elections may be a sign of insufficient resources, high network latency, or disruptions by other components and should be investigated.',
+              description: 'etcd cluster "{{ $labels.%s }}": {{ $value }} leader changes within the last 15 minutes. Frequent elections may be a sign of insufficient resources, high network latency, or disruptions by other components and should be investigated.' % $._config.clusterLabel,
               summary: 'etcd cluster has high number of leader changes.',
             },
           },
@@ -98,7 +100,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": {{ $value }}% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": {{ $value }}%% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster has high number of failed grpc requests.',
             },
           },
@@ -115,7 +117,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": {{ $value }}% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": {{ $value }}%% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster has high number of failed grpc requests.',
             },
           },
@@ -130,7 +132,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": 99th percentile of gRPC requests is {{ $value }}s on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": 99th percentile of gRPC requests is {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd grpc requests are slow',
             },
           },
@@ -145,7 +147,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": member communication with {{ $labels.To }} is taking {{ $value }}s on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": member communication with {{ $labels.To }} is taking {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster member communication is slow.',
             },
           },
@@ -159,7 +161,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": {{ $value }} proposal failures within the last 30 minutes on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": {{ $value }} proposal failures within the last 30 minutes on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster has high number of proposal failures.',
             },
           },
@@ -174,7 +176,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": 99th percentile fsync durations are {{ $value }}s on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": 99th percentile fsync durations are {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster 99th percentile fsync durations are too high.',
             },
           },
@@ -189,7 +191,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": 99th percentile fsync durations are {{ $value }}s on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": 99th percentile fsync durations are {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
             },
           },
           {
@@ -203,7 +205,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": 99th percentile commit durations {{ $value }}s on etcd instance {{ $labels.instance }}.',
+              description: 'etcd cluster "{{ $labels.%s }}": 99th percentile commit durations {{ $value }}s on etcd instance {{ $labels.instance }}.' % $._config.clusterLabel,
               summary: 'etcd cluster 99th percentile commit durations are too high.',
             },
           },
@@ -217,7 +219,7 @@
               severity: 'critical',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": database size exceeds the defined quota on etcd instance {{ $labels.instance }}, please defrag or increase the quota as the writes to etcd will be disabled when it is full.',
+              description: 'etcd cluster "{{ $labels.%s }}": database size exceeds the defined quota on etcd instance {{ $labels.instance }}, please defrag or increase the quota as the writes to etcd will be disabled when it is full.' % $._config.clusterLabel,
             },
           },
           {
@@ -230,7 +232,7 @@
               severity: 'warning',
             },
             annotations: {
-              description: 'etcd cluster "{{ $labels.job }}": Observed surge in etcd writes leading to 50% increase in database size over the past four hours on etcd instance {{ $labels.instance }}, please check as it might be disruptive.',
+              description: 'etcd cluster "{{ $labels.%s }}": Observed surge in etcd writes leading to 50%% increase in database size over the past four hours on etcd instance {{ $labels.instance }}, please check as it might be disruptive.' % $._config.clusterLabel,
             },
           },
         ],
@@ -310,7 +312,7 @@
                 show: false,
               },
               targets: [{
-                expr: 'sum(etcd_server_has_leader{job="$cluster"})',
+                expr: 'sum(etcd_server_has_leader{%s="$cluster"})' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '',
                 metric: 'etcd_server_has_leader',
@@ -360,7 +362,7 @@
               steppedLine: false,
               targets: [
                 {
-                  expr: 'sum(rate(grpc_server_started_total{job="$cluster",grpc_type="unary"}[5m]))',
+                  expr: 'sum(rate(grpc_server_started_total{%s="$cluster",grpc_type="unary"}[5m]))' % $._config.clusterLabel,
                   format: 'time_series',
                   intervalFactor: 2,
                   legendFormat: 'RPC Rate',
@@ -369,7 +371,7 @@
                   step: 2,
                 },
                 {
-                  expr: 'sum(rate(grpc_server_handled_total{job="$cluster",grpc_type="unary",grpc_code=~"Unknown|FailedPrecondition|ResourceExhausted|Internal|Unavailable|DataLoss|DeadlineExceeded"}[5m]))',
+                  expr: 'sum(rate(grpc_server_handled_total{%s="$cluster",grpc_type="unary",grpc_code=~"Unknown|FailedPrecondition|ResourceExhausted|Internal|Unavailable|DataLoss|DeadlineExceeded"}[5m]))' % $._config.clusterLabel,
                   format: 'time_series',
                   intervalFactor: 2,
                   legendFormat: 'RPC Failed Rate',
@@ -446,7 +448,7 @@
               steppedLine: false,
               targets: [
                 {
-                  expr: 'sum(grpc_server_started_total{job="$cluster",grpc_service="etcdserverpb.Watch",grpc_type="bidi_stream"}) - sum(grpc_server_handled_total{job="$cluster",grpc_service="etcdserverpb.Watch",grpc_type="bidi_stream"})',
+                  expr: 'sum(grpc_server_started_total{%(clusterLabel)s="$cluster",grpc_service="etcdserverpb.Watch",grpc_type="bidi_stream"}) - sum(grpc_server_handled_total{%(clusterLabel)s="$cluster",grpc_service="etcdserverpb.Watch",grpc_type="bidi_stream"})' % $._config,
                   intervalFactor: 2,
                   legendFormat: 'Watch Streams',
                   metric: 'grpc_server_handled_total',
@@ -454,7 +456,7 @@
                   step: 4,
                 },
                 {
-                  expr: 'sum(grpc_server_started_total{job="$cluster",grpc_service="etcdserverpb.Lease",grpc_type="bidi_stream"}) - sum(grpc_server_handled_total{job="$cluster",grpc_service="etcdserverpb.Lease",grpc_type="bidi_stream"})',
+                  expr: 'sum(grpc_server_started_total{%(clusterLabel)s="$cluster",grpc_service="etcdserverpb.Lease",grpc_type="bidi_stream"}) - sum(grpc_server_handled_total{%(clusterLabel)s="$cluster",grpc_service="etcdserverpb.Lease",grpc_type="bidi_stream"})' % $._config,
                   intervalFactor: 2,
                   legendFormat: 'Lease Streams',
                   metric: 'grpc_server_handled_total',
@@ -539,7 +541,7 @@
               stack: false,
               steppedLine: false,
               targets: [{
-                expr: 'etcd_mvcc_db_total_size_in_bytes{job="$cluster"}',
+                expr: 'etcd_mvcc_db_total_size_in_bytes{%s="$cluster"}' % $._config.clusterLabel,
                 hide: false,
                 interval: '',
                 intervalFactor: 2,
@@ -614,7 +616,7 @@
               steppedLine: true,
               targets: [
                 {
-                  expr: 'histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{job="$cluster"}[5m])) by (instance, le))',
+                  expr: 'histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket{%s="$cluster"}[5m])) by (instance, le))' % $._config.clusterLabel,
                   hide: false,
                   intervalFactor: 2,
                   legendFormat: '{{instance}} WAL fsync',
@@ -623,7 +625,7 @@
                   step: 4,
                 },
                 {
-                  expr: 'histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job="$cluster"}[5m])) by (instance, le))',
+                  expr: 'histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{%s="$cluster"}[5m])) by (instance, le))' % $._config.clusterLabel,
                   intervalFactor: 2,
                   legendFormat: '{{instance}} DB fsync',
                   metric: 'etcd_disk_backend_commit_duration_seconds_bucket',
@@ -696,7 +698,7 @@
               stack: false,
               steppedLine: false,
               targets: [{
-                expr: 'process_resident_memory_bytes{job="$cluster"}',
+                expr: 'process_resident_memory_bytes{%s="$cluster"}' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '{{instance}} Resident Memory',
                 metric: 'process_resident_memory_bytes',
@@ -778,7 +780,7 @@
               stack: true,
               steppedLine: false,
               targets: [{
-                expr: 'rate(etcd_network_client_grpc_received_bytes_total{job="$cluster"}[5m])',
+                expr: 'rate(etcd_network_client_grpc_received_bytes_total{%s="$cluster"}[5m])' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '{{instance}} Client Traffic In',
                 metric: 'etcd_network_client_grpc_received_bytes_total',
@@ -852,7 +854,7 @@
               stack: true,
               steppedLine: false,
               targets: [{
-                expr: 'rate(etcd_network_client_grpc_sent_bytes_total{job="$cluster"}[5m])',
+                expr: 'rate(etcd_network_client_grpc_sent_bytes_total{%s="$cluster"}[5m])' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '{{instance}} Client Traffic Out',
                 metric: 'etcd_network_client_grpc_sent_bytes_total',
@@ -926,7 +928,7 @@
               stack: false,
               steppedLine: false,
               targets: [{
-                expr: 'sum(rate(etcd_network_peer_received_bytes_total{job="$cluster"}[5m])) by (instance)',
+                expr: 'sum(rate(etcd_network_peer_received_bytes_total{%s="$cluster"}[5m])) by (instance)' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '{{instance}} Peer Traffic In',
                 metric: 'etcd_network_peer_received_bytes_total',
@@ -1001,7 +1003,7 @@
               stack: false,
               steppedLine: false,
               targets: [{
-                expr: 'sum(rate(etcd_network_peer_sent_bytes_total{job="$cluster"}[5m])) by (instance)',
+                expr: 'sum(rate(etcd_network_peer_sent_bytes_total{%s="$cluster"}[5m])) by (instance)' % $._config.clusterLabel,
                 hide: false,
                 interval: '',
                 intervalFactor: 2,
@@ -1084,7 +1086,7 @@
               steppedLine: false,
               targets: [
                 {
-                  expr: 'sum(rate(etcd_server_proposals_failed_total{job="$cluster"}[5m]))',
+                  expr: 'sum(rate(etcd_server_proposals_failed_total{%s="$cluster"}[5m]))' % $._config.clusterLabel,
                   intervalFactor: 2,
                   legendFormat: 'Proposal Failure Rate',
                   metric: 'etcd_server_proposals_failed_total',
@@ -1092,7 +1094,7 @@
                   step: 2,
                 },
                 {
-                  expr: 'sum(etcd_server_proposals_pending{job="$cluster"})',
+                  expr: 'sum(etcd_server_proposals_pending{%s="$cluster"})' % $._config.clusterLabel,
                   intervalFactor: 2,
                   legendFormat: 'Proposal Pending Total',
                   metric: 'etcd_server_proposals_pending',
@@ -1100,7 +1102,7 @@
                   step: 2,
                 },
                 {
-                  expr: 'sum(rate(etcd_server_proposals_committed_total{job="$cluster"}[5m]))',
+                  expr: 'sum(rate(etcd_server_proposals_committed_total{%s="$cluster"}[5m]))' % $._config.clusterLabel,
                   intervalFactor: 2,
                   legendFormat: 'Proposal Commit Rate',
                   metric: 'etcd_server_proposals_committed_total',
@@ -1108,7 +1110,7 @@
                   step: 2,
                 },
                 {
-                  expr: 'sum(rate(etcd_server_proposals_applied_total{job="$cluster"}[5m]))',
+                  expr: 'sum(rate(etcd_server_proposals_applied_total{%s="$cluster"}[5m]))' % $._config.clusterLabel,
                   intervalFactor: 2,
                   legendFormat: 'Proposal Apply Rate',
                   refId: 'D',
@@ -1185,7 +1187,7 @@
               stack: false,
               steppedLine: false,
               targets: [{
-                expr: 'changes(etcd_server_leader_changes_seen_total{job="$cluster"}[1d])',
+                expr: 'changes(etcd_server_leader_changes_seen_total{%s="$cluster"}[1d])' % $._config.clusterLabel,
                 intervalFactor: 2,
                 legendFormat: '{{instance}} Total Leader Elections Per Day',
                 metric: 'etcd_server_leader_changes_seen_total',
@@ -1228,6 +1230,115 @@
                 },
               ],
             },
+            {
+              aliasColors: {},
+              bars: false,
+              dashLength: 10,
+              dashes: false,
+              datasource: '$datasource',
+              decimals: 0,
+              editable: true,
+              'error': false,
+              fieldConfig: {
+                defaults: {
+                  custom: {},
+                },
+                overrides: [],
+              },
+              fill: 0,
+              fillGradient: 0,
+              gridPos: {
+                h: 7,
+                w: 12,
+                x: 0,
+                y: 28,
+              },
+              hiddenSeries: false,
+              id: 42,
+              isNew: true,
+              legend: {
+                alignAsTable: false,
+                avg: false,
+                current: false,
+                max: false,
+                min: false,
+                rightSide: false,
+                show: false,
+                total: false,
+                values: false,
+              },
+              lines: true,
+              linewidth: 2,
+              links: [],
+              nullPointMode: 'connected',
+              options: {
+                alertThreshold: true,
+              },
+              percentage: false,
+              pluginVersion: '7.4.3',
+              pointradius: 5,
+              points: false,
+              renderer: 'flot',
+              seriesOverrides: [],
+              spaceLength: 10,
+              stack: false,
+              steppedLine: false,
+              targets: [
+                {
+                  expr: 'histogram_quantile(0.99, sum by (instance, le) (rate(etcd_network_peer_round_trip_time_seconds_bucket{%s="$cluster"}[5m])))' % $._config.clusterLabel,
+                  interval: '',
+                  intervalFactor: 2,
+                  legendFormat: '{{instance}} Peer round trip time',
+                  metric: 'etcd_network_peer_round_trip_time_seconds_bucket',
+                  refId: 'A',
+                  step: 2,
+                },
+              ],
+              thresholds: [],
+              timeFrom: null,
+              timeRegions: [],
+              timeShift: null,
+              title: 'Peer round trip time',
+              tooltip: {
+                msResolution: false,
+                shared: true,
+                sort: 0,
+                value_type: 'individual',
+              },
+              type: 'graph',
+              xaxis: {
+                buckets: null,
+                mode: 'time',
+                name: null,
+                show: true,
+                values: [],
+              },
+              yaxes: [
+                {
+                  '$$hashKey': 'object:925',
+                  decimals: null,
+                  format: 's',
+                  label: null,
+                  logBase: 1,
+                  max: null,
+                  min: null,
+                  show: true,
+                },
+                {
+                  '$$hashKey': 'object:926',
+                  format: 'short',
+                  label: null,
+                  logBase: 1,
+                  max: null,
+                  min: null,
+                  show: true,
+                },
+              ],
+              yaxis: {
+                align: false,
+                alignLevel: null,
+              },
+            },
           ],
           title: 'New row',
         },
@@ -1291,7 +1402,7 @@
             multi: false,
             name: 'cluster',
             options: [],
-            query: 'label_values(etcd_server_has_leader, job)',
+            query: 'label_values(etcd_server_has_leader, %s)' % $._config.clusterLabel,
             refresh: $._config.dashboard_var_refresh,
             regex: '',
             sort: 2,
diff --git a/contrib/raftexample/raft.go b/contrib/raftexample/raft.go
index b2bcb25..439a083 100644
--- a/contrib/raftexample/raft.go
+++ b/contrib/raftexample/raft.go
@@ -31,8 +31,8 @@
 	"go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
 	stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 
 	"go.uber.org/zap"
 )
diff --git a/etcdctl/go.sum b/etcdctl/go.sum
index a3551e7..c640b20 100644
--- a/etcdctl/go.sum
+++ b/etcdctl/go.sum
@@ -78,8 +78,6 @@
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -98,6 +96,8 @@
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
diff --git a/etcdutl/ctl.go b/etcdutl/ctl.go
index 2d74684..967a780 100644
--- a/etcdutl/ctl.go
+++ b/etcdutl/ctl.go
@@ -45,6 +45,7 @@
 		etcdutl.NewSnapshotCommand(),
 		etcdutl.NewVersionCommand(),
 		etcdutl.NewCompletionCommand(),
+		etcdutl.NewMigrateCommand(),
 	)
 }
 
diff --git a/etcdutl/etcdutl/backup_command.go b/etcdutl/etcdutl/backup_command.go
index bf8ede3..54fa68e 100644
--- a/etcdutl/etcdutl/backup_command.go
+++ b/etcdutl/etcdutl/backup_command.go
@@ -27,15 +27,15 @@
 	"go.etcd.io/etcd/pkg/v3/idutil"
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/datadir"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
 	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 	"go.etcd.io/etcd/server/v3/storage/schema"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.etcd.io/etcd/server/v3/verify"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
 
 	bolt "go.etcd.io/bbolt"
 	"go.uber.org/zap"
diff --git a/etcdutl/etcdutl/defrag_command.go b/etcdutl/etcdutl/defrag_command.go
index 67880c0..fe4f843 100644
--- a/etcdutl/etcdutl/defrag_command.go
+++ b/etcdutl/etcdutl/defrag_command.go
@@ -21,8 +21,8 @@
 
 	"github.com/spf13/cobra"
 	"go.etcd.io/etcd/pkg/v3/cobrautl"
-	"go.etcd.io/etcd/server/v3/datadir"
 	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 )
 
 var (
diff --git a/etcdutl/etcdutl/migrate_command.go b/etcdutl/etcdutl/migrate_command.go
new file mode 100644
index 0000000..d83ed82
--- /dev/null
+++ b/etcdutl/etcdutl/migrate_command.go
@@ -0,0 +1,141 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etcdutl
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/coreos/go-semver/semver"
+	"github.com/spf13/cobra"
+	"go.uber.org/zap"
+
+	"go.etcd.io/etcd/pkg/v3/cobrautl"
+	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
+	"go.etcd.io/etcd/server/v3/storage/schema"
+)
+
+// NewMigrateCommand prints out the version of etcd.
+func NewMigrateCommand() *cobra.Command {
+	o := newMigrateOptions()
+	cmd := &cobra.Command{
+		Use:   "migrate",
+		Short: "Migrates schema of etcd data dir files to make them compatible with different etcd version",
+		Run: func(cmd *cobra.Command, args []string) {
+			cfg, err := o.Config()
+			if err != nil {
+				cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
+			}
+			err = migrateCommandFunc(cfg)
+			if err != nil {
+				cobrautl.ExitWithError(cobrautl.ExitError, err)
+			}
+		},
+	}
+	o.AddFlags(cmd)
+	return cmd
+}
+
+type migrateOptions struct {
+	dataDir       string
+	targetVersion string
+	force         bool
+}
+
+func newMigrateOptions() *migrateOptions {
+	return &migrateOptions{}
+}
+
+func (o *migrateOptions) AddFlags(cmd *cobra.Command) {
+	cmd.Flags().StringVar(&o.dataDir, "data-dir", o.dataDir, "Path to the etcd data dir")
+	cmd.MarkFlagRequired("data-dir")
+	cmd.MarkFlagDirname("data-dir")
+
+	cmd.Flags().StringVar(&o.targetVersion, "target-version", o.targetVersion, `Target etcd version to migrate contents of data dir. Minimal value 3.5. Format "X.Y" for example 3.6.`)
+	cmd.MarkFlagRequired("target-version")
+
+	cmd.Flags().BoolVar(&o.force, "force", o.force, "Ignore migration failure and forcefully override storage version. Not recommended.")
+}
+
+func (o *migrateOptions) Config() (*migrateConfig, error) {
+	c := &migrateConfig{
+		force: o.force,
+	}
+	var err error
+	dotCount := strings.Count(o.targetVersion, ".")
+	if dotCount != 1 {
+		return nil, fmt.Errorf(`wrong target version format, expected "X.Y", got %q`, o.targetVersion)
+	}
+	c.targetVersion, err = semver.NewVersion(o.targetVersion + ".0")
+	if err != nil {
+		return nil, fmt.Errorf("failed to parse target version: %w", err)
+	}
+	if c.targetVersion.LessThan(schema.V3_5) {
+		return nil, fmt.Errorf(`target version %q not supported. Minimal "3.5"`, storageVersionToString(c.targetVersion))
+	}
+
+	dbPath := datadir.ToBackendFileName(o.dataDir)
+	c.be = backend.NewDefaultBackend(dbPath)
+
+	return c, nil
+}
+
+type migrateConfig struct {
+	be            backend.Backend
+	targetVersion *semver.Version
+	force         bool
+}
+
+func migrateCommandFunc(c *migrateConfig) error {
+	defer c.be.Close()
+	lg := GetLogger()
+	tx := c.be.BatchTx()
+	tx.Lock()
+	current, err := schema.DetectSchemaVersion(lg, tx)
+	if err != nil {
+		tx.Unlock()
+		lg.Error("failed to detect storage version. Please make sure you are using data dir from etcd v3.5 and older")
+		return err
+	}
+	if *current == *c.targetVersion {
+		tx.Unlock()
+		lg.Info("storage version up-to-date", zap.String("storage-version", storageVersionToString(current)))
+		return nil
+	}
+	if c.force {
+		unsafeMigrateForce(lg, tx, c.targetVersion)
+		tx.Unlock()
+		c.be.ForceCommit()
+		return nil
+	}
+	tx.Unlock()
+	return fmt.Errorf("storage version migration is not yet supported")
+}
+
+func unsafeMigrateForce(lg *zap.Logger, tx backend.BatchTx, target *semver.Version) {
+	// Storage version is only supported since v3.6
+	if target.LessThan(schema.V3_6) {
+		schema.UnsafeClearStorageVersion(tx)
+		lg.Warn("forcefully cleared storage version")
+	} else {
+		schema.UnsafeSetStorageVersion(tx, target)
+		lg.Warn("forcefully set storage version", zap.String("storage-version", storageVersionToString(target)))
+	}
+}
+
+func storageVersionToString(ver *semver.Version) string {
+	return fmt.Sprintf("%d.%d", ver.Major, ver.Minor)
+}
diff --git a/etcdutl/etcdutl/snapshot_command.go b/etcdutl/etcdutl/snapshot_command.go
index 0ff6183..1b3f5ef 100644
--- a/etcdutl/etcdutl/snapshot_command.go
+++ b/etcdutl/etcdutl/snapshot_command.go
@@ -20,7 +20,7 @@
 
 	"go.etcd.io/etcd/etcdutl/v3/snapshot"
 	"go.etcd.io/etcd/pkg/v3/cobrautl"
-	"go.etcd.io/etcd/server/v3/datadir"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 
 	"github.com/spf13/cobra"
 )
diff --git a/etcdutl/go.mod b/etcdutl/go.mod
index 7535704..53c1475 100644
--- a/etcdutl/go.mod
+++ b/etcdutl/go.mod
@@ -21,6 +21,7 @@
 )
 
 require (
+	github.com/coreos/go-semver v0.3.0
 	github.com/dustin/go-humanize v1.0.0
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/spf13/cobra v1.1.3
diff --git a/etcdutl/go.sum b/etcdutl/go.sum
index 02dce4d..1e13b31 100644
--- a/etcdutl/go.sum
+++ b/etcdutl/go.sum
@@ -74,8 +74,6 @@
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -94,6 +92,8 @@
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
diff --git a/etcdutl/snapshot/v3_snapshot.go b/etcdutl/snapshot/v3_snapshot.go
index 36fc9ee..f644549 100644
--- a/etcdutl/snapshot/v3_snapshot.go
+++ b/etcdutl/snapshot/v3_snapshot.go
@@ -42,9 +42,9 @@
 	"go.etcd.io/etcd/server/v3/etcdserver/cindex"
 	"go.etcd.io/etcd/server/v3/storage/backend"
 	"go.etcd.io/etcd/server/v3/storage/schema"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.etcd.io/etcd/server/v3/verify"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
 	"go.uber.org/zap"
 )
 
diff --git a/go.sum b/go.sum
index e69cbee..f3c8f35 100644
--- a/go.sum
+++ b/go.sum
@@ -79,8 +79,6 @@
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -99,6 +97,8 @@
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
diff --git a/raft/go.mod b/raft/go.mod
index c7fd9b4..ff7bd60 100644
--- a/raft/go.mod
+++ b/raft/go.mod
@@ -8,6 +8,7 @@
 	github.com/gogo/protobuf v1.3.2
 	github.com/golang/protobuf v1.5.2
 	github.com/pkg/errors v0.9.1 // indirect
+	go.etcd.io/etcd/api/v3 v3.5.0
 	go.etcd.io/etcd/client/pkg/v3 v3.5.0
 )
 
@@ -18,3 +19,5 @@
 replace go.etcd.io/etcd/v3 => ./FORBIDDEN_DEPENDENCY
 
 replace go.etcd.io/etcd/client/pkg/v3 => ../client/pkg
+
+replace go.etcd.io/etcd/api/v3 => ../api
diff --git a/raft/go.sum b/raft/go.sum
index c5eabef..fdb6f30 100644
--- a/raft/go.sum
+++ b/raft/go.sum
@@ -1,27 +1,61 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
 github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs=
 github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
 github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY=
 github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -35,49 +69,112 @@
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/raft/raft.go b/raft/raft.go
index 73ed83c..5e3026a 100644
--- a/raft/raft.go
+++ b/raft/raft.go
@@ -662,7 +662,7 @@
 		r.electionElapsed = 0
 		if r.checkQuorum {
 			if err := r.Step(pb.Message{From: r.id, Type: pb.MsgCheckQuorum}); err != nil {
-				r.logger.Debugf("error occurred during checking sending hearbeat: %v", err)
+				r.logger.Debugf("error occurred during checking sending heartbeat: %v", err)
 			}
 		}
 		// If current leader cannot transfer leadership in electionTimeout, it becomes leader again.
@@ -678,7 +678,7 @@
 	if r.heartbeatElapsed >= r.heartbeatTimeout {
 		r.heartbeatElapsed = 0
 		if err := r.Step(pb.Message{From: r.id, Type: pb.MsgBeat}); err != nil {
-			r.logger.Debugf("error occurred during checking sending hearbeat: %v", err)
+			r.logger.Debugf("error occurred during checking sending heartbeat: %v", err)
 		}
 	}
 }
diff --git a/raft/raftpb/raft.pb.go b/raft/raftpb/raft.pb.go
index 1ee77a9..d2eaa5d 100644
--- a/raft/raftpb/raft.pb.go
+++ b/raft/raftpb/raft.pb.go
@@ -11,6 +11,7 @@
 
 	_ "github.com/gogo/protobuf/gogoproto"
 	proto "github.com/golang/protobuf/proto"
+	_ "go.etcd.io/etcd/api/v3/versionpb"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
@@ -695,72 +696,75 @@
 func init() { proto.RegisterFile("raft.proto", fileDescriptor_b042552c306ae59b) }
 
 var fileDescriptor_b042552c306ae59b = []byte{
-	// 1026 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xdb, 0x46,
-	0x17, 0x25, 0x29, 0x5a, 0x3f, 0x57, 0xb2, 0x3c, 0xbe, 0xf1, 0x17, 0x10, 0x86, 0xc1, 0xe8, 0x53,
-	0x52, 0x44, 0x70, 0x11, 0xb7, 0xd0, 0xa2, 0x28, 0xba, 0xf3, 0x4f, 0x00, 0xab, 0xb0, 0xdc, 0x54,
-	0x76, 0xbc, 0x28, 0x50, 0x08, 0x63, 0x71, 0x44, 0xb3, 0x15, 0x39, 0x04, 0x39, 0x72, 0xed, 0x4d,
-	0x51, 0xf4, 0x09, 0xba, 0xec, 0x26, 0xdb, 0x3e, 0x40, 0x9f, 0xc2, 0x4b, 0x03, 0xdd, 0x74, 0x15,
-	0x34, 0xf6, 0x8b, 0x14, 0x33, 0x1c, 0x4a, 0x94, 0x6c, 0x64, 0xd1, 0xdd, 0xcc, 0xb9, 0x67, 0xee,
-	0x9c, 0x73, 0xef, 0xe5, 0x10, 0x20, 0xa1, 0x63, 0xb1, 0x13, 0x27, 0x5c, 0x70, 0x2c, 0xcb, 0x75,
-	0x7c, 0xbe, 0xb9, 0xe1, 0x73, 0x9f, 0x2b, 0xe8, 0x33, 0xb9, 0xca, 0xa2, 0xed, 0x9f, 0x61, 0xe5,
-	0x75, 0x24, 0x92, 0x6b, 0x74, 0xc0, 0x3e, 0x65, 0x49, 0xe8, 0x58, 0x2d, 0xb3, 0x63, 0xef, 0xd9,
-	0x37, 0xef, 0x9f, 0x19, 0x03, 0x85, 0xe0, 0x26, 0xac, 0xf4, 0x22, 0x8f, 0x5d, 0x39, 0xa5, 0x42,
-	0x28, 0x83, 0xf0, 0x53, 0xb0, 0x4f, 0xaf, 0x63, 0xe6, 0x98, 0x2d, 0xb3, 0xd3, 0xec, 0xae, 0xef,
-	0x64, 0x77, 0xed, 0xa8, 0x94, 0x32, 0x30, 0x4b, 0x74, 0x1d, 0x33, 0x44, 0xb0, 0x0f, 0xa8, 0xa0,
-	0x8e, 0xdd, 0x32, 0x3b, 0x8d, 0x81, 0x5a, 0xb7, 0x7f, 0x31, 0x81, 0x9c, 0x44, 0x34, 0x4e, 0x2f,
-	0xb8, 0xe8, 0x33, 0x41, 0x3d, 0x2a, 0x28, 0x7e, 0x01, 0x30, 0xe2, 0xd1, 0x78, 0x98, 0x0a, 0x2a,
-	0xb2, 0xdc, 0xf5, 0x79, 0xee, 0x7d, 0x1e, 0x8d, 0x4f, 0x64, 0x40, 0xe7, 0xae, 0x8d, 0x72, 0x40,
-	0x2a, 0x0d, 0x94, 0xd2, 0xa2, 0x89, 0x0c, 0x92, 0xfe, 0x84, 0xf4, 0x57, 0x34, 0xa1, 0x90, 0xf6,
-	0x77, 0x50, 0xcd, 0x15, 0x48, 0x89, 0x52, 0x81, 0xba, 0xb3, 0x31, 0x50, 0x6b, 0xfc, 0x0a, 0xaa,
-	0xa1, 0x56, 0xa6, 0x12, 0xd7, 0xbb, 0x4e, 0xae, 0x65, 0x59, 0xb9, 0xce, 0x3b, 0xe3, 0xb7, 0xdf,
-	0x95, 0xa0, 0xd2, 0x67, 0x69, 0x4a, 0x7d, 0x86, 0xaf, 0xc0, 0x16, 0xf3, 0x5a, 0x3d, 0xc9, 0x73,
-	0xe8, 0x70, 0xb1, 0x5a, 0x92, 0x86, 0x1b, 0x60, 0x09, 0xbe, 0xe0, 0xc4, 0x12, 0x5c, 0xda, 0x18,
-	0x27, 0x7c, 0xc9, 0x86, 0x44, 0x66, 0x06, 0xed, 0x65, 0x83, 0xe8, 0x42, 0x65, 0xc2, 0x7d, 0xd5,
-	0xdd, 0x95, 0x42, 0x30, 0x07, 0xe7, 0x65, 0x2b, 0x3f, 0x2c, 0xdb, 0x2b, 0xa8, 0xb0, 0x48, 0x24,
-	0x01, 0x4b, 0x9d, 0x4a, 0xab, 0xd4, 0xa9, 0x77, 0x57, 0x17, 0x7a, 0x9c, 0xa7, 0xd2, 0x1c, 0xdc,
-	0x82, 0xf2, 0x88, 0x87, 0x61, 0x20, 0x9c, 0x6a, 0x21, 0x97, 0xc6, 0xb0, 0x0b, 0xd5, 0x54, 0x57,
-	0xcc, 0xa9, 0xa9, 0x4a, 0x92, 0xe5, 0x4a, 0xe6, 0x15, 0xcc, 0x79, 0x32, 0x63, 0xc2, 0x7e, 0x60,
-	0x23, 0xe1, 0x40, 0xcb, 0xec, 0x54, 0xf3, 0x8c, 0x19, 0x86, 0x2f, 0x00, 0xb2, 0xd5, 0x61, 0x10,
-	0x09, 0xa7, 0x5e, 0xb8, 0xb3, 0x80, 0xa3, 0x03, 0x95, 0x11, 0x8f, 0x04, 0xbb, 0x12, 0x4e, 0x43,
-	0x35, 0x36, 0xdf, 0xb6, 0xbf, 0x87, 0xda, 0x21, 0x4d, 0xbc, 0x6c, 0x7c, 0xf2, 0x0a, 0x9a, 0x0f,
-	0x2a, 0xe8, 0x80, 0x7d, 0xc9, 0x05, 0x5b, 0xfc, 0x38, 0x24, 0x52, 0x30, 0x5c, 0x7a, 0x68, 0xb8,
-	0xfd, 0xa7, 0x09, 0xb5, 0xd9, 0xbc, 0xe2, 0x53, 0x28, 0xcb, 0x33, 0x49, 0xea, 0x98, 0xad, 0x52,
-	0xc7, 0x1e, 0xe8, 0x1d, 0x6e, 0x42, 0x75, 0xc2, 0x68, 0x12, 0xc9, 0x88, 0xa5, 0x22, 0xb3, 0x3d,
-	0xbe, 0x84, 0xb5, 0x8c, 0x35, 0xe4, 0x53, 0xe1, 0xf3, 0x20, 0xf2, 0x9d, 0x92, 0xa2, 0x34, 0x33,
-	0xf8, 0x1b, 0x8d, 0xe2, 0x73, 0x58, 0xcd, 0x0f, 0x0d, 0x23, 0xe9, 0xd4, 0x56, 0xb4, 0x46, 0x0e,
-	0x1e, 0xb3, 0x2b, 0x81, 0xcf, 0x01, 0xe8, 0x54, 0xf0, 0xe1, 0x84, 0xd1, 0x4b, 0xa6, 0x86, 0x21,
-	0x2f, 0x68, 0x4d, 0xe2, 0x47, 0x12, 0x6e, 0xbf, 0x33, 0x01, 0xa4, 0xe8, 0xfd, 0x0b, 0x1a, 0xf9,
-	0x0c, 0x3f, 0xd7, 0x63, 0x6b, 0xa9, 0xb1, 0x7d, 0x5a, 0xfc, 0x0c, 0x33, 0xc6, 0x83, 0xc9, 0x7d,
-	0x09, 0x95, 0x88, 0x7b, 0x6c, 0x18, 0x78, 0xba, 0x28, 0x4d, 0x19, 0xbc, 0x7b, 0xff, 0xac, 0x7c,
-	0xcc, 0x3d, 0xd6, 0x3b, 0x18, 0x94, 0x65, 0xb8, 0xe7, 0x15, 0xfb, 0x62, 0x2f, 0xf4, 0x05, 0x37,
-	0xc1, 0x0a, 0x3c, 0xdd, 0x08, 0xd0, 0xa7, 0xad, 0xde, 0xc1, 0xc0, 0x0a, 0xbc, 0x76, 0x08, 0x64,
-	0x7e, 0xf9, 0x49, 0x10, 0xf9, 0x93, 0xb9, 0x48, 0xf3, 0xbf, 0x88, 0xb4, 0x3e, 0x26, 0xb2, 0xfd,
-	0x87, 0x09, 0x8d, 0x79, 0x9e, 0xb3, 0x2e, 0xee, 0x01, 0x88, 0x84, 0x46, 0x69, 0x20, 0x02, 0x1e,
-	0xe9, 0x1b, 0xb7, 0x1e, 0xb9, 0x71, 0xc6, 0xc9, 0x27, 0x72, 0x7e, 0x0a, 0xbf, 0x84, 0xca, 0x48,
-	0xb1, 0xb2, 0x8e, 0x17, 0x9e, 0x94, 0x65, 0x6b, 0xf9, 0x17, 0xa6, 0xe9, 0xc5, 0x9a, 0x95, 0x16,
-	0x6a, 0xb6, 0x7d, 0x08, 0xb5, 0xd9, 0xbb, 0x8b, 0x6b, 0x50, 0x57, 0x9b, 0x63, 0x9e, 0x84, 0x74,
-	0x42, 0x0c, 0x7c, 0x02, 0x6b, 0x0a, 0x98, 0xe7, 0x27, 0x26, 0xfe, 0x0f, 0xd6, 0x97, 0xc0, 0xb3,
-	0x2e, 0xb1, 0xb6, 0xff, 0xb2, 0xa0, 0x5e, 0x78, 0x96, 0x10, 0xa0, 0xdc, 0x4f, 0xfd, 0xc3, 0x69,
-	0x4c, 0x0c, 0xac, 0x43, 0xa5, 0x9f, 0xfa, 0x7b, 0x8c, 0x0a, 0x62, 0xea, 0xcd, 0x9b, 0x84, 0xc7,
-	0xc4, 0xd2, 0xac, 0xdd, 0x38, 0x26, 0x25, 0x6c, 0x02, 0x64, 0xeb, 0x01, 0x4b, 0x63, 0x62, 0x6b,
-	0xe2, 0x19, 0x17, 0x8c, 0xac, 0x48, 0x6d, 0x7a, 0xa3, 0xa2, 0x65, 0x1d, 0x95, 0x4f, 0x00, 0xa9,
-	0x20, 0x81, 0x86, 0xbc, 0x8c, 0xd1, 0x44, 0x9c, 0xcb, 0x5b, 0xaa, 0xb8, 0x01, 0xa4, 0x88, 0xa8,
-	0x43, 0x35, 0x44, 0x68, 0xf6, 0x53, 0xff, 0x6d, 0x94, 0x30, 0x3a, 0xba, 0xa0, 0xe7, 0x13, 0x46,
-	0x00, 0xd7, 0x61, 0x55, 0x27, 0x92, 0x5f, 0xdc, 0x34, 0x25, 0x75, 0x4d, 0xdb, 0xbf, 0x60, 0xa3,
-	0x1f, 0xbf, 0x9d, 0xf2, 0x64, 0x1a, 0x92, 0x86, 0xb4, 0xdd, 0x4f, 0x7d, 0xd5, 0xa0, 0x31, 0x4b,
-	0x8e, 0x18, 0xf5, 0x58, 0x42, 0x56, 0xf5, 0xe9, 0xd3, 0x20, 0x64, 0x7c, 0x2a, 0x8e, 0xf9, 0x4f,
-	0xa4, 0xa9, 0xc5, 0x0c, 0x18, 0xf5, 0xd4, 0xff, 0x8e, 0xac, 0x69, 0x31, 0x33, 0x44, 0x89, 0x21,
-	0xda, 0xef, 0x9b, 0x84, 0x29, 0x8b, 0xeb, 0xfa, 0x56, 0xbd, 0x57, 0x1c, 0xdc, 0xfe, 0xd5, 0x84,
-	0x8d, 0xc7, 0xc6, 0x03, 0xb7, 0xc0, 0x79, 0x0c, 0xdf, 0x9d, 0x0a, 0x4e, 0x0c, 0xfc, 0x04, 0xfe,
-	0xff, 0x58, 0xf4, 0x6b, 0x1e, 0x44, 0xa2, 0x17, 0xc6, 0x93, 0x60, 0x14, 0xc8, 0x56, 0x7c, 0x8c,
-	0xf6, 0xfa, 0x4a, 0xd3, 0xac, 0xed, 0x6b, 0x68, 0x2e, 0x7e, 0x14, 0xb2, 0x18, 0x73, 0x64, 0xd7,
-	0xf3, 0xe4, 0xf8, 0x13, 0x03, 0x9d, 0xa2, 0xd8, 0x01, 0x0b, 0xf9, 0x25, 0x53, 0x11, 0x73, 0x31,
-	0xf2, 0x36, 0xf6, 0xa8, 0xc8, 0x22, 0xd6, 0xa2, 0x91, 0x5d, 0xcf, 0x3b, 0xca, 0xde, 0x1e, 0x15,
-	0x2d, 0xed, 0xbd, 0xb8, 0xf9, 0xe0, 0x1a, 0xb7, 0x1f, 0x5c, 0xe3, 0xe6, 0xce, 0x35, 0x6f, 0xef,
-	0x5c, 0xf3, 0x9f, 0x3b, 0xd7, 0xfc, 0xed, 0xde, 0x35, 0x7e, 0xbf, 0x77, 0x8d, 0xdb, 0x7b, 0xd7,
-	0xf8, 0xfb, 0xde, 0x35, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xee, 0xe3, 0x39, 0x8b, 0xbb, 0x08,
-	0x00, 0x00,
+	// 1079 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcf, 0x6b, 0xe3, 0x46,
+	0x14, 0x96, 0x64, 0xc5, 0xb2, 0x9f, 0x1d, 0x67, 0x32, 0x9b, 0x2e, 0xc2, 0x2c, 0x5a, 0xd7, 0xbb,
+	0x65, 0x4d, 0xca, 0x26, 0x8b, 0xbb, 0x94, 0xb2, 0xb7, 0xfc, 0x58, 0x48, 0x4a, 0x9c, 0x6e, 0x9d,
+	0x6c, 0x0e, 0x0b, 0x25, 0x4c, 0xac, 0xb1, 0xa2, 0xd6, 0xd6, 0x88, 0xd1, 0x38, 0x4d, 0x6e, 0xa5,
+	0x97, 0x1e, 0x7a, 0x29, 0x3d, 0x95, 0x42, 0xaf, 0xbd, 0x16, 0x0a, 0xfd, 0x1f, 0x72, 0x0c, 0xf4,
+	0xd2, 0xd3, 0xd2, 0x4d, 0xfe, 0x91, 0x32, 0xa3, 0x91, 0x25, 0x3b, 0x61, 0x0f, 0xbd, 0xcd, 0x7c,
+	0xef, 0xd3, 0x7b, 0xdf, 0xfb, 0xde, 0xcc, 0x08, 0x80, 0x93, 0xa1, 0x58, 0x8b, 0x39, 0x13, 0x0c,
+	0x97, 0xe5, 0x3a, 0x3e, 0x69, 0xae, 0x04, 0x2c, 0x60, 0x0a, 0x5a, 0x97, 0xab, 0x34, 0xda, 0x6c,
+	0x51, 0x31, 0xf0, 0xd7, 0x49, 0x1c, 0xae, 0x9f, 0x51, 0x9e, 0x84, 0x2c, 0x8a, 0x4f, 0xb2, 0x55,
+	0xca, 0x68, 0xff, 0x60, 0xc2, 0xc2, 0xcb, 0x48, 0xf0, 0x0b, 0xec, 0x82, 0x7d, 0x48, 0xf9, 0xd8,
+	0xb5, 0x5a, 0x66, 0xc7, 0xde, 0xb4, 0x2f, 0xdf, 0x3e, 0x34, 0xfa, 0x0a, 0xc1, 0x4d, 0x58, 0xd8,
+	0x8d, 0x7c, 0x7a, 0xee, 0x96, 0x0a, 0xa1, 0x14, 0xc2, 0x1f, 0x83, 0x7d, 0x78, 0x11, 0x53, 0xd7,
+	0x6c, 0x99, 0x9d, 0x46, 0x77, 0x79, 0x2d, 0x95, 0xb3, 0xa6, 0x52, 0xca, 0xc0, 0x34, 0xd1, 0x45,
+	0x4c, 0x31, 0x06, 0x7b, 0x9b, 0x08, 0xe2, 0xda, 0x2d, 0xb3, 0x53, 0xef, 0xab, 0xf5, 0x0b, 0xe7,
+	0xfb, 0xbf, 0xdc, 0xd2, 0x27, 0x6b, 0xcf, 0xda, 0xdf, 0x99, 0x80, 0x0e, 0x22, 0x12, 0x27, 0xa7,
+	0x4c, 0xf4, 0xa8, 0x20, 0x3e, 0x11, 0x04, 0x7f, 0x0a, 0x30, 0x60, 0xd1, 0xf0, 0x38, 0x11, 0x44,
+	0xa4, 0x45, 0x6a, 0x79, 0x91, 0x2d, 0x16, 0x0d, 0x0f, 0x64, 0x40, 0x17, 0xa9, 0x0e, 0x32, 0x40,
+	0x4a, 0x0e, 0x95, 0xe4, 0x62, 0x37, 0x29, 0x24, 0x1b, 0x15, 0xb2, 0xd1, 0x62, 0x37, 0x0a, 0x69,
+	0xbf, 0x81, 0x4a, 0xa6, 0x40, 0x6a, 0x95, 0x0a, 0x54, 0xcd, 0x7a, 0x5f, 0xad, 0xf1, 0x0b, 0xa8,
+	0x8c, 0xb5, 0x32, 0x95, 0xb8, 0xd6, 0x75, 0x33, 0x2d, 0xf3, 0xca, 0x75, 0xde, 0x29, 0xbf, 0xfd,
+	0x5b, 0x09, 0x9c, 0x1e, 0x4d, 0x12, 0x12, 0x50, 0xfc, 0x14, 0x6c, 0x91, 0x9b, 0x76, 0x2f, 0xcb,
+	0xa1, 0xc3, 0x45, 0xdb, 0x24, 0x0d, 0xaf, 0x80, 0x25, 0xd8, 0x4c, 0x27, 0x96, 0x60, 0xb2, 0x8d,
+	0x21, 0x67, 0x73, 0x6d, 0x48, 0x64, 0xda, 0xa0, 0x3d, 0xdf, 0x20, 0xf6, 0xc0, 0x19, 0xb1, 0x40,
+	0x8d, 0x79, 0xa1, 0x10, 0xcc, 0xc0, 0xdc, 0xb6, 0xf2, 0x6d, 0xdb, 0x9e, 0x82, 0x43, 0x23, 0xc1,
+	0x43, 0x9a, 0xb8, 0x4e, 0xab, 0xd4, 0xa9, 0x75, 0x17, 0x67, 0x86, 0x9d, 0xa5, 0xd2, 0x1c, 0xfc,
+	0x00, 0xca, 0x03, 0x36, 0x1e, 0x87, 0xc2, 0xad, 0x14, 0x72, 0x69, 0x0c, 0x77, 0xa1, 0x92, 0x68,
+	0xc7, 0xdc, 0xaa, 0x72, 0x12, 0xcd, 0x3b, 0x99, 0x39, 0x98, 0xf1, 0x64, 0x46, 0x4e, 0xbf, 0xa6,
+	0x03, 0xe1, 0x42, 0xcb, 0xec, 0x54, 0xb2, 0x8c, 0x29, 0x86, 0x1f, 0x03, 0xa4, 0xab, 0x9d, 0x30,
+	0x12, 0x6e, 0xad, 0x50, 0xb3, 0x80, 0x63, 0x17, 0x9c, 0x01, 0x8b, 0x04, 0x3d, 0x17, 0x6e, 0x5d,
+	0x0d, 0x36, 0xdb, 0xb6, 0xbf, 0x82, 0xea, 0x0e, 0xe1, 0x7e, 0x7a, 0x7c, 0x32, 0x07, 0xcd, 0x5b,
+	0x0e, 0xba, 0x60, 0x9f, 0x31, 0x41, 0x67, 0x6f, 0x89, 0x44, 0x0a, 0x0d, 0x97, 0x6e, 0x37, 0xdc,
+	0xfe, 0xd3, 0x84, 0xea, 0xf4, 0xbc, 0xe2, 0xfb, 0x50, 0x96, 0xdf, 0xf0, 0xc4, 0x35, 0x5b, 0xa5,
+	0x8e, 0xdd, 0xd7, 0x3b, 0xdc, 0x84, 0xca, 0x88, 0x12, 0x1e, 0xc9, 0x88, 0xa5, 0x22, 0xd3, 0x3d,
+	0x7e, 0x02, 0x4b, 0x29, 0xeb, 0x98, 0x4d, 0x44, 0xc0, 0xc2, 0x28, 0x70, 0x4b, 0x8a, 0xd2, 0x48,
+	0xe1, 0x2f, 0x34, 0x8a, 0x1f, 0xc1, 0x62, 0xf6, 0xd1, 0x71, 0x24, 0x3b, 0xb5, 0x15, 0xad, 0x9e,
+	0x81, 0xfb, 0xf4, 0x5c, 0xe0, 0x47, 0x00, 0x64, 0x22, 0xd8, 0xf1, 0x88, 0x92, 0x33, 0xaa, 0x0e,
+	0x43, 0x66, 0x68, 0x55, 0xe2, 0x7b, 0x12, 0x6e, 0xff, 0x6e, 0x02, 0x48, 0xd1, 0x5b, 0xa7, 0x24,
+	0x0a, 0x28, 0x7e, 0xa6, 0x8f, 0xad, 0xa5, 0x8e, 0xed, 0xfd, 0xe2, 0x35, 0x4c, 0x19, 0xb7, 0x4e,
+	0xee, 0x13, 0x70, 0x22, 0xe6, 0xd3, 0xe3, 0xd0, 0xd7, 0xa6, 0x34, 0x64, 0xf0, 0xfa, 0xed, 0xc3,
+	0xf2, 0x3e, 0xf3, 0xe9, 0xee, 0x76, 0xbf, 0x2c, 0xc3, 0xbb, 0x7e, 0x71, 0x2e, 0xf6, 0xcc, 0x5c,
+	0x70, 0x13, 0xac, 0xd0, 0xd7, 0x83, 0x00, 0xfd, 0xb5, 0xb5, 0xbb, 0xdd, 0xb7, 0x42, 0x3f, 0x7f,
+	0x3b, 0xc6, 0x80, 0x72, 0x15, 0x07, 0x61, 0x14, 0x8c, 0x72, 0xb5, 0xe6, 0xff, 0x51, 0x6b, 0xbd,
+	0x4f, 0x6d, 0xfb, 0x0f, 0x13, 0xea, 0x79, 0x9e, 0xa3, 0x2e, 0xde, 0x04, 0x10, 0x9c, 0x44, 0x49,
+	0x28, 0x42, 0x16, 0xe9, 0x8a, 0x0f, 0xee, 0xa8, 0x38, 0xe5, 0x64, 0x47, 0x33, 0xff, 0x0a, 0x7f,
+	0x06, 0xce, 0x40, 0xb1, 0xd2, 0xd1, 0x17, 0xde, 0x96, 0xf9, 0xd6, 0xb2, 0xab, 0xa6, 0xe9, 0x45,
+	0xf3, 0x4a, 0x33, 0xe6, 0x65, 0x06, 0x3d, 0x5f, 0x7d, 0x03, 0xd5, 0xe9, 0x93, 0x8c, 0x97, 0xa0,
+	0xa6, 0x36, 0xfb, 0x8c, 0x8f, 0xc9, 0x08, 0x19, 0xf8, 0x1e, 0x2c, 0x29, 0x20, 0x2f, 0x84, 0x4c,
+	0xec, 0xc1, 0xf2, 0x1c, 0x78, 0xd4, 0x45, 0x56, 0xd3, 0xf9, 0x35, 0x4d, 0xd9, 0x74, 0x7e, 0x4e,
+	0xcd, 0x5f, 0xfd, 0xdb, 0x82, 0x5a, 0xe1, 0xe9, 0xc2, 0x00, 0xe5, 0x5e, 0x12, 0xec, 0x4c, 0x62,
+	0x64, 0xe0, 0x1a, 0x38, 0xbd, 0x24, 0xd8, 0xa4, 0x44, 0x20, 0x53, 0x6f, 0x5e, 0x71, 0x16, 0x23,
+	0x4b, 0xb3, 0x36, 0xe2, 0x18, 0x95, 0x70, 0x03, 0x20, 0x5d, 0xf7, 0x69, 0x12, 0x23, 0x5b, 0x13,
+	0x8f, 0x98, 0xa0, 0x68, 0x41, 0xaa, 0xd5, 0x1b, 0x15, 0x2d, 0xeb, 0xa8, 0x7c, 0x26, 0x90, 0x83,
+	0x11, 0xd4, 0x65, 0x31, 0x4a, 0xb8, 0x38, 0x91, 0x55, 0x2a, 0x78, 0x05, 0x50, 0x11, 0x51, 0x1f,
+	0x55, 0x31, 0x86, 0x46, 0x2f, 0x09, 0x5e, 0x47, 0x9c, 0x92, 0xc1, 0x29, 0x39, 0x19, 0x51, 0x04,
+	0x78, 0x19, 0x16, 0x75, 0x22, 0x79, 0x2b, 0x27, 0x09, 0xaa, 0x69, 0xda, 0xd6, 0x29, 0x1d, 0x7c,
+	0xf3, 0xe5, 0x84, 0xf1, 0xc9, 0x18, 0xd5, 0xf1, 0x07, 0xb0, 0xdc, 0x4b, 0x02, 0x35, 0xbb, 0x21,
+	0xe5, 0x7b, 0x94, 0xf8, 0x94, 0xa3, 0x45, 0xfd, 0xf5, 0x61, 0x38, 0xa6, 0x6c, 0x22, 0xf6, 0xd9,
+	0xb7, 0xa8, 0xa1, 0xc5, 0xf4, 0x29, 0xf1, 0xd5, 0xcf, 0x11, 0x2d, 0x69, 0x31, 0x53, 0x44, 0x89,
+	0x41, 0xba, 0xdf, 0x57, 0x9c, 0xaa, 0x16, 0x97, 0x75, 0x55, 0xbd, 0x57, 0x1c, 0xbc, 0xfa, 0xa3,
+	0x09, 0x2b, 0x77, 0x9d, 0x1c, 0xfc, 0x00, 0xdc, 0xbb, 0xf0, 0x8d, 0x89, 0x60, 0xc8, 0xc0, 0x1f,
+	0xc1, 0x87, 0x77, 0x45, 0x3f, 0x67, 0x61, 0x24, 0x76, 0xc7, 0xf1, 0x28, 0x1c, 0x84, 0x72, 0x14,
+	0xef, 0xa3, 0xbd, 0x3c, 0xd7, 0x34, 0x2b, 0x9b, 0xf1, 0xf3, 0xd5, 0x0b, 0x68, 0xcc, 0x5e, 0x1c,
+	0xe9, 0x4a, 0x8e, 0x6c, 0xf8, 0xbe, 0xbc, 0x22, 0xc8, 0xc0, 0x6e, 0x51, 0x75, 0x9f, 0x8e, 0xd9,
+	0x19, 0x55, 0x11, 0x73, 0x36, 0xf2, 0x3a, 0xf6, 0x89, 0x48, 0x23, 0xd6, 0x6c, 0x47, 0x1b, 0xbe,
+	0xbf, 0x97, 0x3e, 0x54, 0x2a, 0x5a, 0xda, 0x7c, 0x7c, 0xf9, 0xce, 0x33, 0xae, 0xde, 0x79, 0xc6,
+	0xe5, 0xb5, 0x67, 0x5e, 0x5d, 0x7b, 0xe6, 0xbf, 0xd7, 0x9e, 0xf9, 0xd3, 0x8d, 0x67, 0xfc, 0x72,
+	0xe3, 0x19, 0x57, 0x37, 0x9e, 0xf1, 0xcf, 0x8d, 0x67, 0xfc, 0x17, 0x00, 0x00, 0xff, 0xff, 0x96,
+	0xae, 0xd0, 0x97, 0x14, 0x09, 0x00, 0x00,
 }
 
 func (m *Entry) Marshal() (dAtA []byte, err error) {
diff --git a/raft/raftpb/raft.proto b/raft/raftpb/raft.proto
index f46a54c..931fb0b 100644
--- a/raft/raftpb/raft.proto
+++ b/raft/raftpb/raft.proto
@@ -2,6 +2,7 @@
 package raftpb;
 
 import "gogoproto/gogo.proto";
+import "etcd/api/versionpb/version.proto";
 
 option (gogoproto.marshaler_all) = true;
 option (gogoproto.sizer_all) = true;
@@ -13,12 +14,16 @@
 option (gogoproto.goproto_sizecache_all) = false;
 
 enum EntryType {
+	option (versionpb.etcd_version_enum) = "3.0";
+
 	EntryNormal       = 0;
 	EntryConfChange   = 1; // corresponds to pb.ConfChange
-	EntryConfChangeV2 = 2; // corresponds to pb.ConfChangeV2
+	EntryConfChangeV2 = 2 [(versionpb.etcd_version_enum_value)="3.4"]; // corresponds to pb.ConfChangeV2
 }
 
 message Entry {
+	option (versionpb.etcd_version_msg) = "3.0";
+
 	optional uint64     Term  = 2 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
 	optional uint64     Index = 3 [(gogoproto.nullable) = false]; // must be 64-bit aligned for atomic operations
 	optional EntryType  Type  = 1 [(gogoproto.nullable) = false];
@@ -89,6 +94,7 @@
 // ConfChangeTransition specifies the behavior of a configuration change with
 // respect to joint consensus.
 enum ConfChangeTransition {
+	option (versionpb.etcd_version_enum) = "3.4";
 	// Automatically use the simple protocol if possible, otherwise fall back
 	// to ConfChangeJointImplicit. Most applications will want to use this.
 	ConfChangeTransitionAuto          = 0;
@@ -131,14 +137,16 @@
 }
 
 message ConfChange {
+	option (versionpb.etcd_version_msg) = "3.0";
+
 	optional ConfChangeType  type    = 2 [(gogoproto.nullable) = false];
-	optional uint64          node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID" ];
+	optional uint64          node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID"];
 	optional bytes           context = 4;
 
 	// NB: this is used only by etcd to thread through a unique identifier.
 	// Ideally it should really use the Context instead. No counterpart to
 	// this field exists in ConfChangeV2.
-	optional uint64          id      = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID" ];
+	optional uint64          id      = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID"];
 }
 
 // ConfChangeSingle is an individual configuration change operation. Multiple
@@ -181,6 +189,8 @@
 //
 // [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf
 message ConfChangeV2 {
+	option (versionpb.etcd_version_msg) = "3.4";
+
 	optional ConfChangeTransition transition = 1 [(gogoproto.nullable) = false];
 	repeated ConfChangeSingle     changes =    2 [(gogoproto.nullable) = false];
 	optional bytes                context =    3;
diff --git a/scripts/genproto.sh b/scripts/genproto.sh
index c340724..03392c6 100755
--- a/scripts/genproto.sh
+++ b/scripts/genproto.sh
@@ -34,7 +34,7 @@
 GOGOPROTO_PATH="${GOGOPROTO_ROOT}:${GOGOPROTO_ROOT}/protobuf"
 
 # directories containing protos to be built
-DIRS="./server/wal/walpb ./api/etcdserverpb ./server/etcdserver/api/snap/snappb ./raft/raftpb ./api/mvccpb ./server/lease/leasepb ./api/authpb ./server/etcdserver/api/v3lock/v3lockpb ./server/etcdserver/api/v3election/v3electionpb ./api/membershippb ./tests/functional"
+DIRS="./server/wal/walpb ./api/etcdserverpb ./server/etcdserver/api/snap/snappb ./raft/raftpb ./api/mvccpb ./server/lease/leasepb ./api/authpb ./server/etcdserver/api/v3lock/v3lockpb ./server/etcdserver/api/v3election/v3electionpb ./api/membershippb ./tests/functional ./api/versionpb"
 
 log_callout -e "\\nRunning gofast (gogo) proto generation..."
 
@@ -45,6 +45,7 @@
 
     run sed -i.bak -E 's|"etcd/api/|"go.etcd.io/etcd/api/v3/|g' ./**/*.pb.go
     run sed -i.bak -E 's|"raft/raftpb"|"go.etcd.io/etcd/raft/v3/raftpb"|g' ./**/*.pb.go
+    run sed -i.bak -E 's|"google/protobuf"|"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"|g' ./**/*.pb.go
 
     rm -f ./**/*.bak
     run gofmt -s -w ./**/*.pb.go
diff --git a/server/auth/jwt.go b/server/auth/jwt.go
index d286f92..dce741f 100644
--- a/server/auth/jwt.go
+++ b/server/auth/jwt.go
@@ -21,7 +21,7 @@
 	"errors"
 	"time"
 
-	jwt "github.com/form3tech-oss/jwt-go"
+	jwt "github.com/golang-jwt/jwt"
 	"go.uber.org/zap"
 )
 
diff --git a/server/auth/options.go b/server/auth/options.go
index c0b039f..d4cb8ab 100644
--- a/server/auth/options.go
+++ b/server/auth/options.go
@@ -21,7 +21,7 @@
 	"io/ioutil"
 	"time"
 
-	jwt "github.com/form3tech-oss/jwt-go"
+	jwt "github.com/golang-jwt/jwt"
 )
 
 const (
diff --git a/server/config/config.go b/server/config/config.go
index de59994..c9e7d3a 100644
--- a/server/config/config.go
+++ b/server/config/config.go
@@ -25,7 +25,7 @@
 	"go.etcd.io/etcd/client/pkg/v3/transport"
 	"go.etcd.io/etcd/client/pkg/v3/types"
 	"go.etcd.io/etcd/pkg/v3/netutil"
-	"go.etcd.io/etcd/server/v3/datadir"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
 
 	bolt "go.etcd.io/bbolt"
@@ -121,7 +121,8 @@
 	// MaxRequestBytes is the maximum request size to send over raft.
 	MaxRequestBytes uint
 
-	WarningApplyDuration time.Duration
+	WarningApplyDuration        time.Duration
+	WarningUnaryRequestDuration time.Duration
 
 	StrictReconfigCheck bool
 
diff --git a/server/embed/config.go b/server/embed/config.go
index 044b133..a0f195c 100644
--- a/server/embed/config.go
+++ b/server/embed/config.go
@@ -49,16 +49,17 @@
 	ClusterStateFlagNew      = "new"
 	ClusterStateFlagExisting = "existing"
 
-	DefaultName                  = "default"
-	DefaultMaxSnapshots          = 5
-	DefaultMaxWALs               = 5
-	DefaultMaxTxnOps             = uint(128)
-	DefaultWarningApplyDuration  = 100 * time.Millisecond
-	DefaultMaxRequestBytes       = 1.5 * 1024 * 1024
-	DefaultGRPCKeepAliveMinTime  = 5 * time.Second
-	DefaultGRPCKeepAliveInterval = 2 * time.Hour
-	DefaultGRPCKeepAliveTimeout  = 20 * time.Second
-	DefaultDowngradeCheckTime    = 5 * time.Second
+	DefaultName                        = "default"
+	DefaultMaxSnapshots                = 5
+	DefaultMaxWALs                     = 5
+	DefaultMaxTxnOps                   = uint(128)
+	DefaultWarningApplyDuration        = 100 * time.Millisecond
+	DefaultWarningUnaryRequestDuration = 300 * time.Millisecond
+	DefaultMaxRequestBytes             = 1.5 * 1024 * 1024
+	DefaultGRPCKeepAliveMinTime        = 5 * time.Second
+	DefaultGRPCKeepAliveInterval       = 2 * time.Hour
+	DefaultGRPCKeepAliveTimeout        = 20 * time.Second
+	DefaultDowngradeCheckTime          = 5 * time.Second
 
 	DefaultListenPeerURLs   = "http://localhost:2380"
 	DefaultListenClientURLs = "http://localhost:2379"
@@ -326,6 +327,9 @@
 	// ExperimentalBootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to
 	// consider running defrag during bootstrap. Needs to be set to non-zero value to take effect.
 	ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"`
+	// ExperimentalWarningUnaryRequestDuration is the time duration after which a warning is generated if applying
+	// unary request takes more time than this value.
+	ExperimentalWarningUnaryRequestDuration time.Duration `json:"experimental-warning-unary-request-duration"`
 
 	// ForceNewCluster starts a new cluster even if previously started; unsafe.
 	ForceNewCluster bool `json:"force-new-cluster"`
@@ -447,6 +451,8 @@
 		MaxRequestBytes:                  DefaultMaxRequestBytes,
 		ExperimentalWarningApplyDuration: DefaultWarningApplyDuration,
 
+		ExperimentalWarningUnaryRequestDuration: DefaultWarningUnaryRequestDuration,
+
 		GRPCKeepAliveMinTime:  DefaultGRPCKeepAliveMinTime,
 		GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval,
 		GRPCKeepAliveTimeout:  DefaultGRPCKeepAliveTimeout,
diff --git a/server/embed/etcd.go b/server/embed/etcd.go
index 8e5ac15..af27e35 100644
--- a/server/embed/etcd.go
+++ b/server/embed/etcd.go
@@ -42,6 +42,7 @@
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v2v3"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3client"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc"
+	"go.etcd.io/etcd/server/v3/storage"
 	"go.etcd.io/etcd/server/v3/verify"
 
 	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
@@ -221,6 +222,7 @@
 		WatchProgressNotifyInterval:              cfg.ExperimentalWatchProgressNotifyInterval,
 		DowngradeCheckTime:                       cfg.ExperimentalDowngradeCheckTime,
 		WarningApplyDuration:                     cfg.ExperimentalWarningApplyDuration,
+		WarningUnaryRequestDuration:              cfg.ExperimentalWarningUnaryRequestDuration,
 		ExperimentalMemoryMlock:                  cfg.ExperimentalMemoryMlock,
 		ExperimentalTxnModeWriteWithSharedBuffer: cfg.ExperimentalTxnModeWriteWithSharedBuffer,
 		ExperimentalBootstrapDefragThresholdMegabytes: cfg.ExperimentalBootstrapDefragThresholdMegabytes,
@@ -302,7 +304,7 @@
 
 	quota := ec.QuotaBackendBytes
 	if quota == 0 {
-		quota = etcdserver.DefaultQuotaBytes
+		quota = storage.DefaultQuotaBytes
 	}
 
 	lg.Info(
diff --git a/server/embed/util.go b/server/embed/util.go
index ad46153..269fbc8 100644
--- a/server/embed/util.go
+++ b/server/embed/util.go
@@ -17,7 +17,7 @@
 import (
 	"path/filepath"
 
-	"go.etcd.io/etcd/server/v3/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal"
 )
 
 func isMemberInitialized(cfg *Config) bool {
diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go
index 5dadbf6..7840083 100644
--- a/server/etcdmain/config.go
+++ b/server/etcdmain/config.go
@@ -286,6 +286,7 @@
 	fs.DurationVar(&cfg.ec.ExperimentalWatchProgressNotifyInterval, "experimental-watch-progress-notify-interval", cfg.ec.ExperimentalWatchProgressNotifyInterval, "Duration of periodic watch progress notifications.")
 	fs.DurationVar(&cfg.ec.ExperimentalDowngradeCheckTime, "experimental-downgrade-check-time", cfg.ec.ExperimentalDowngradeCheckTime, "Duration of time between two downgrade status check.")
 	fs.DurationVar(&cfg.ec.ExperimentalWarningApplyDuration, "experimental-warning-apply-duration", cfg.ec.ExperimentalWarningApplyDuration, "Time duration after which a warning is generated if request takes more time.")
+	fs.DurationVar(&cfg.ec.ExperimentalWarningUnaryRequestDuration, "experimental-warning-unary-request-duration", cfg.ec.ExperimentalWarningUnaryRequestDuration, "Time duration after which a warning is generated if a unary request takes more time.")
 	fs.BoolVar(&cfg.ec.ExperimentalMemoryMlock, "experimental-memory-mlock", cfg.ec.ExperimentalMemoryMlock, "Enable to enforce etcd pages (in particular bbolt) to stay in RAM.")
 	fs.BoolVar(&cfg.ec.ExperimentalTxnModeWriteWithSharedBuffer, "experimental-txn-mode-write-with-shared-buffer", true, "Enable the write transaction to use a shared buffer in its readonly check operations.")
 	fs.UintVar(&cfg.ec.ExperimentalBootstrapDefragThresholdMegabytes, "experimental-bootstrap-defrag-threshold-megabytes", 0, "Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect.")
diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go
index dc5b55f..8460738 100644
--- a/server/etcdmain/help.go
+++ b/server/etcdmain/help.go
@@ -246,6 +246,8 @@
     Enable the write transaction to use a shared buffer in its readonly check operations.
   --experimental-bootstrap-defrag-threshold-megabytes
     Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect.
+  --experimental-warning-unary-request-duration '300ms'
+    Set time duration after which a warning is generated if a unary request takes more than this duration.
 
 Unsafe feature:
   --force-new-cluster 'false'
diff --git a/server/etcdserver/api/snap/snapshotter.go b/server/etcdserver/api/snap/snapshotter.go
index 52cc0ae..70e946d 100644
--- a/server/etcdserver/api/snap/snapshotter.go
+++ b/server/etcdserver/api/snap/snapshotter.go
@@ -31,7 +31,7 @@
 	"go.etcd.io/etcd/raft/v3"
 	"go.etcd.io/etcd/raft/v3/raftpb"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 
 	"go.uber.org/zap"
 )
diff --git a/server/etcdserver/api/snap/snapshotter_test.go b/server/etcdserver/api/snap/snapshotter_test.go
index 40ad084..52a378d 100644
--- a/server/etcdserver/api/snap/snapshotter_test.go
+++ b/server/etcdserver/api/snap/snapshotter_test.go
@@ -25,7 +25,7 @@
 
 	"go.etcd.io/etcd/client/pkg/v3/fileutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.uber.org/zap"
 )
 
diff --git a/server/etcdserver/api/v3rpc/interceptor.go b/server/etcdserver/api/v3rpc/interceptor.go
index 5c80fcf..0d4d5c3 100644
--- a/server/etcdserver/api/v3rpc/interceptor.go
+++ b/server/etcdserver/api/v3rpc/interceptor.go
@@ -33,9 +33,8 @@
 )
 
 const (
-	maxNoLeaderCnt          = 3
-	warnUnaryRequestLatency = 300 * time.Millisecond
-	snapshotMethod          = "/etcdserverpb.Maintenance/Snapshot"
+	maxNoLeaderCnt = 3
+	snapshotMethod = "/etcdserverpb.Maintenance/Snapshot"
 )
 
 type streamsMap struct {
@@ -78,19 +77,19 @@
 		resp, err := handler(ctx, req)
 		lg := s.Logger()
 		if lg != nil { // acquire stats if debug level is enabled or request is expensive
-			defer logUnaryRequestStats(ctx, lg, info, startTime, req, resp)
+			defer logUnaryRequestStats(ctx, lg, s.Cfg.WarningUnaryRequestDuration, info, startTime, req, resp)
 		}
 		return resp, err
 	}
 }
 
-func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) {
+func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, warnLatency time.Duration, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) {
 	duration := time.Since(startTime)
 	var enabledDebugLevel, expensiveRequest bool
 	if lg.Core().Enabled(zap.DebugLevel) {
 		enabledDebugLevel = true
 	}
-	if duration > warnUnaryRequestLatency {
+	if duration > warnLatency {
 		expensiveRequest = true
 	}
 	if !enabledDebugLevel && !expensiveRequest {
diff --git a/server/etcdserver/api/v3rpc/quota.go b/server/etcdserver/api/v3rpc/quota.go
index 7f53bd9..fd41bc1 100644
--- a/server/etcdserver/api/v3rpc/quota.go
+++ b/server/etcdserver/api/v3rpc/quota.go
@@ -21,6 +21,7 @@
 	"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
 	"go.etcd.io/etcd/client/pkg/v3/types"
 	"go.etcd.io/etcd/server/v3/etcdserver"
+	"go.etcd.io/etcd/server/v3/storage"
 )
 
 type quotaKVServer struct {
@@ -29,7 +30,7 @@
 }
 
 type quotaAlarmer struct {
-	q  etcdserver.Quota
+	q  storage.Quota
 	a  Alarmer
 	id types.ID
 }
@@ -52,7 +53,7 @@
 func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer {
 	return &quotaKVServer{
 		NewKVServer(s),
-		quotaAlarmer{etcdserver.NewBackendQuota(s, "kv"), s, s.ID()},
+		quotaAlarmer{storage.NewBackendQuota(s.Cfg, s.Backend(), "kv"), s, s.ID()},
 	}
 }
 
@@ -85,6 +86,6 @@
 func NewQuotaLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer {
 	return &quotaLeaseServer{
 		NewLeaseServer(s),
-		quotaAlarmer{etcdserver.NewBackendQuota(s, "lease"), s, s.ID()},
+		quotaAlarmer{storage.NewBackendQuota(s.Cfg, s.Backend(), "lease"), s, s.ID()},
 	}
 }
diff --git a/server/etcdserver/apply.go b/server/etcdserver/apply.go
index 5235d61..2f4d9f3 100644
--- a/server/etcdserver/apply.go
+++ b/server/etcdserver/apply.go
@@ -32,6 +32,7 @@
 	"go.etcd.io/etcd/server/v3/etcdserver/api"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
 	"go.etcd.io/etcd/server/v3/lease"
+	serverstorage "go.etcd.io/etcd/server/v3/storage"
 	"go.etcd.io/etcd/server/v3/storage/mvcc"
 
 	"github.com/gogo/protobuf/proto"
@@ -770,7 +771,7 @@
 
 type applierV3Capped struct {
 	applierV3
-	q backendQuota
+	q serverstorage.BackendQuota
 }
 
 // newApplierV3Capped creates an applyV3 that will reject Puts and transactions
@@ -949,11 +950,11 @@
 
 type quotaApplierV3 struct {
 	applierV3
-	q Quota
+	q serverstorage.Quota
 }
 
 func newQuotaApplierV3(s *EtcdServer, app applierV3) applierV3 {
-	return &quotaApplierV3{app, NewBackendQuota(s, "v3-applier")}
+	return &quotaApplierV3{app, serverstorage.NewBackendQuota(s.Cfg, s.Backend(), "v3-applier")}
 }
 
 func (a *quotaApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) {
diff --git a/server/etcdserver/bootstrap.go b/server/etcdserver/bootstrap.go
index 497d06a..9a31f65 100644
--- a/server/etcdserver/bootstrap.go
+++ b/server/etcdserver/bootstrap.go
@@ -41,10 +41,11 @@
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
 	"go.etcd.io/etcd/server/v3/etcdserver/cindex"
+	serverstorage "go.etcd.io/etcd/server/v3/storage"
 	"go.etcd.io/etcd/server/v3/storage/backend"
 	"go.etcd.io/etcd/server/v3/storage/schema"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 )
 
 func bootstrap(cfg config.ServerConfig) (b *bootstrappedServer, err error) {
@@ -117,7 +118,7 @@
 	st      v2store.Store
 	be      backend.Backend
 	ss      *snap.Snapshotter
-	beHooks *backendHooks
+	beHooks *serverstorage.BackendHooks
 }
 
 func bootstrapSnapshot(cfg config.ServerConfig) *snap.Snapshotter {
@@ -141,11 +142,11 @@
 	return snap.New(cfg.Logger, cfg.SnapDir())
 }
 
-func bootstrapBackend(cfg config.ServerConfig) (be backend.Backend, ci cindex.ConsistentIndexer, beExist bool, beHooks *backendHooks, err error) {
+func bootstrapBackend(cfg config.ServerConfig) (be backend.Backend, ci cindex.ConsistentIndexer, beExist bool, beHooks *serverstorage.BackendHooks, err error) {
 	beExist = fileutil.Exist(cfg.BackendPath())
 	ci = cindex.NewConsistentIndex(nil)
-	beHooks = &backendHooks{lg: cfg.Logger, indexer: ci}
-	be = openBackend(cfg, beHooks)
+	beHooks = serverstorage.NewBackendHooks(cfg.Logger, ci)
+	be = serverstorage.OpenBackend(cfg, beHooks)
 	ci.SetBackend(be)
 	schema.CreateMetaBucket(be.BatchTx())
 	if cfg.ExperimentalBootstrapDefragThresholdMegabytes != 0 {
@@ -249,7 +250,7 @@
 	}, nil
 }
 
-func bootstrapWithWAL(cfg config.ServerConfig, st v2store.Store, be backend.Backend, ss *snap.Snapshotter, beExist bool, beHooks *backendHooks, ci cindex.ConsistentIndexer) (*bootstrappedServer, error) {
+func bootstrapWithWAL(cfg config.ServerConfig, st v2store.Store, be backend.Backend, ss *snap.Snapshotter, beExist bool, beHooks *serverstorage.BackendHooks, ci cindex.ConsistentIndexer) (*bootstrappedServer, error) {
 	if err := fileutil.IsDirWriteable(cfg.MemberDir()); err != nil {
 		return nil, fmt.Errorf("cannot write to member directory: %v", err)
 	}
@@ -282,7 +283,7 @@
 			cfg.Logger.Panic("failed to recover from snapshot", zap.Error(err))
 		}
 
-		if err = assertNoV2StoreContent(cfg.Logger, st, cfg.V2Deprecation); err != nil {
+		if err = serverstorage.AssertNoV2StoreContent(cfg.Logger, st, cfg.V2Deprecation); err != nil {
 			cfg.Logger.Error("illegal v2store content", zap.Error(err))
 			return nil, err
 		}
@@ -293,7 +294,7 @@
 			zap.String("snapshot-size", humanize.Bytes(uint64(snapshot.Size()))),
 		)
 
-		if be, err = recoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil {
+		if be, err = serverstorage.RecoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil {
 			cfg.Logger.Panic("failed to recover v3 backend from snapshot", zap.Error(err))
 		}
 		s1, s2 := be.Size(), be.SizeInUse()
@@ -578,9 +579,9 @@
 }
 
 func (wal *bootstrappedWAL) ConfigChangeEntries() []raftpb.Entry {
-	return createConfigChangeEnts(
+	return serverstorage.CreateConfigChangeEnts(
 		wal.lg,
-		getIDs(wal.lg, wal.snapshot, wal.ents),
+		serverstorage.GetIDs(wal.lg, wal.snapshot, wal.ents),
 		uint64(wal.id),
 		wal.st.Term,
 		wal.st.Commit,
diff --git a/server/etcdserver/metrics.go b/server/etcdserver/metrics.go
index 06263a9..33ee027 100644
--- a/server/etcdserver/metrics.go
+++ b/server/etcdserver/metrics.go
@@ -124,12 +124,7 @@
 		Name:      "lease_expired_total",
 		Help:      "The total number of expired leases.",
 	})
-	quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
-		Namespace: "etcd",
-		Subsystem: "server",
-		Name:      "quota_backend_bytes",
-		Help:      "Current backend storage quota size in bytes.",
-	})
+
 	currentVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{
 		Namespace: "etcd",
 		Subsystem: "server",
@@ -191,7 +186,6 @@
 	prometheus.MustRegister(slowReadIndex)
 	prometheus.MustRegister(readIndexFailed)
 	prometheus.MustRegister(leaseExpired)
-	prometheus.MustRegister(quotaBackendBytes)
 	prometheus.MustRegister(currentVersion)
 	prometheus.MustRegister(currentGoVersion)
 	prometheus.MustRegister(serverID)
diff --git a/server/etcdserver/raft.go b/server/etcdserver/raft.go
index 8b30b65..4fb8da6 100644
--- a/server/etcdserver/raft.go
+++ b/server/etcdserver/raft.go
@@ -15,21 +15,16 @@
 package etcdserver
 
 import (
-	"encoding/json"
 	"expvar"
 	"fmt"
 	"log"
-	"sort"
 	"sync"
 	"time"
 
 	"go.etcd.io/etcd/client/pkg/v3/logutil"
-	"go.etcd.io/etcd/client/pkg/v3/types"
 	"go.etcd.io/etcd/pkg/v3/contention"
-	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
 	"go.uber.org/zap"
 )
@@ -415,106 +410,3 @@
 		r.tick()
 	}
 }
-
-// getIDs returns an ordered set of IDs included in the given snapshot and
-// the entries. The given snapshot/entries can contain three kinds of
-// ID-related entry:
-// - ConfChangeAddNode, in which case the contained ID will be added into the set.
-// - ConfChangeRemoveNode, in which case the contained ID will be removed from the set.
-// - ConfChangeAddLearnerNode, in which the contained ID will be added into the set.
-func getIDs(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 {
-	ids := make(map[uint64]bool)
-	if snap != nil {
-		for _, id := range snap.Metadata.ConfState.Voters {
-			ids[id] = true
-		}
-	}
-	for _, e := range ents {
-		if e.Type != raftpb.EntryConfChange {
-			continue
-		}
-		var cc raftpb.ConfChange
-		pbutil.MustUnmarshal(&cc, e.Data)
-		switch cc.Type {
-		case raftpb.ConfChangeAddLearnerNode:
-			ids[cc.NodeID] = true
-		case raftpb.ConfChangeAddNode:
-			ids[cc.NodeID] = true
-		case raftpb.ConfChangeRemoveNode:
-			delete(ids, cc.NodeID)
-		case raftpb.ConfChangeUpdateNode:
-			// do nothing
-		default:
-			lg.Panic("unknown ConfChange Type", zap.String("type", cc.Type.String()))
-		}
-	}
-	sids := make(types.Uint64Slice, 0, len(ids))
-	for id := range ids {
-		sids = append(sids, id)
-	}
-	sort.Sort(sids)
-	return []uint64(sids)
-}
-
-// createConfigChangeEnts creates a series of Raft entries (i.e.
-// EntryConfChange) to remove the set of given IDs from the cluster. The ID
-// `self` is _not_ removed, even if present in the set.
-// If `self` is not inside the given ids, it creates a Raft entry to add a
-// default member with the given `self`.
-func createConfigChangeEnts(lg *zap.Logger, ids []uint64, self uint64, term, index uint64) []raftpb.Entry {
-	found := false
-	for _, id := range ids {
-		if id == self {
-			found = true
-		}
-	}
-
-	var ents []raftpb.Entry
-	next := index + 1
-
-	// NB: always add self first, then remove other nodes. Raft will panic if the
-	// set of voters ever becomes empty.
-	if !found {
-		m := membership.Member{
-			ID:             types.ID(self),
-			RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:2380"}},
-		}
-		ctx, err := json.Marshal(m)
-		if err != nil {
-			lg.Panic("failed to marshal member", zap.Error(err))
-		}
-		cc := &raftpb.ConfChange{
-			Type:    raftpb.ConfChangeAddNode,
-			NodeID:  self,
-			Context: ctx,
-		}
-		e := raftpb.Entry{
-			Type:  raftpb.EntryConfChange,
-			Data:  pbutil.MustMarshal(cc),
-			Term:  term,
-			Index: next,
-		}
-		ents = append(ents, e)
-		next++
-	}
-
-	for _, id := range ids {
-		if id == self {
-			continue
-		}
-		cc := &raftpb.ConfChange{
-			Type:   raftpb.ConfChangeRemoveNode,
-			NodeID: id,
-		}
-		e := raftpb.Entry{
-			Type:  raftpb.EntryConfChange,
-			Data:  pbutil.MustMarshal(cc),
-			Term:  term,
-			Index: next,
-		}
-		ents = append(ents, e)
-		next++
-	}
-
-	return ents
-}
diff --git a/server/etcdserver/raft_test.go b/server/etcdserver/raft_test.go
index 3eb5345..49de844 100644
--- a/server/etcdserver/raft_test.go
+++ b/server/etcdserver/raft_test.go
@@ -28,6 +28,7 @@
 	"go.etcd.io/etcd/raft/v3/raftpb"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
 	"go.etcd.io/etcd/server/v3/mock/mockstorage"
+	serverstorage "go.etcd.io/etcd/server/v3/storage"
 	"go.uber.org/zap"
 )
 
@@ -66,7 +67,7 @@
 		if tt.confState != nil {
 			snap.Metadata.ConfState = *tt.confState
 		}
-		idSet := getIDs(testLogger, &snap, tt.ents)
+		idSet := serverstorage.GetIDs(testLogger, &snap, tt.ents)
 		if !reflect.DeepEqual(idSet, tt.widSet) {
 			t.Errorf("#%d: idset = %#v, want %#v", i, idSet, tt.widSet)
 		}
@@ -146,7 +147,7 @@
 	}
 
 	for i, tt := range tests {
-		gents := createConfigChangeEnts(testLogger, tt.ids, tt.self, tt.term, tt.index)
+		gents := serverstorage.CreateConfigChangeEnts(testLogger, tt.ids, tt.self, tt.term, tt.index)
 		if !reflect.DeepEqual(gents, tt.wents) {
 			t.Errorf("#%d: ents = %v, want %v", i, gents, tt.wents)
 		}
diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go
index 95db2a2..590c98c 100644
--- a/server/etcdserver/server.go
+++ b/server/etcdserver/server.go
@@ -62,6 +62,7 @@
 	serverversion "go.etcd.io/etcd/server/v3/etcdserver/version"
 	"go.etcd.io/etcd/server/v3/lease"
 	"go.etcd.io/etcd/server/v3/lease/leasehttp"
+	serverstorage "go.etcd.io/etcd/server/v3/storage"
 	"go.etcd.io/etcd/server/v3/storage/backend"
 	"go.etcd.io/etcd/server/v3/storage/mvcc"
 	"go.etcd.io/etcd/server/v3/storage/schema"
@@ -258,7 +259,7 @@
 	lessor     lease.Lessor
 	bemu       sync.Mutex
 	be         backend.Backend
-	beHooks    *backendHooks
+	beHooks    *serverstorage.BackendHooks
 	authStore  auth.AuthStore
 	alarmStore *v3alarm.AlarmStore
 
@@ -296,36 +297,6 @@
 	updateStorageSchema sync.Once
 }
 
-type backendHooks struct {
-	indexer cindex.ConsistentIndexer
-	lg      *zap.Logger
-
-	// confState to be written in the next submitted backend transaction (if dirty)
-	confState raftpb.ConfState
-	// first write changes it to 'dirty'. false by default, so
-	// not initialized `confState` is meaningless.
-	confStateDirty bool
-	confStateLock  sync.Mutex
-}
-
-func (bh *backendHooks) OnPreCommitUnsafe(tx backend.BatchTx) {
-	bh.indexer.UnsafeSave(tx)
-	bh.confStateLock.Lock()
-	defer bh.confStateLock.Unlock()
-	if bh.confStateDirty {
-		schema.MustUnsafeSaveConfStateToBackend(bh.lg, tx, &bh.confState)
-		// save bh.confState
-		bh.confStateDirty = false
-	}
-}
-
-func (bh *backendHooks) SetConfState(confState *raftpb.ConfState) {
-	bh.confStateLock.Lock()
-	defer bh.confStateLock.Unlock()
-	bh.confState = *confState
-	bh.confStateDirty = true
-}
-
 // NewServer creates a new EtcdServer from the supplied configuration. The
 // configuration is considered static for the lifetime of the EtcdServer.
 func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) {
@@ -462,23 +433,6 @@
 	return srv, nil
 }
 
-// assertNoV2StoreContent -> depending on the deprecation stage, warns or report an error
-// if the v2store contains custom content.
-func assertNoV2StoreContent(lg *zap.Logger, st v2store.Store, deprecationStage config.V2DeprecationEnum) error {
-	metaOnly, err := membership.IsMetaStoreOnly(st)
-	if err != nil {
-		return err
-	}
-	if metaOnly {
-		return nil
-	}
-	if deprecationStage.IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) {
-		return fmt.Errorf("detected disallowed custom content in v2store for stage --v2-deprecation=%s", deprecationStage)
-	}
-	lg.Warn("detected custom v2store content. Etcd v3.5 is the last version allowing to access it using API v2. Please remove the content.")
-	return nil
-}
-
 func (s *EtcdServer) Logger() *zap.Logger {
 	s.lgMu.RLock()
 	l := s.lg
@@ -1006,7 +960,7 @@
 	// wait for raftNode to persist snapshot onto the disk
 	<-apply.notifyc
 
-	newbe, err := openSnapshotBackend(s.Cfg, s.snapshotter, apply.snapshot, s.beHooks)
+	newbe, err := serverstorage.OpenSnapshotBackend(s.Cfg, s.snapshotter, apply.snapshot, s.beHooks)
 	if err != nil {
 		lg.Panic("failed to open snapshot backend", zap.Error(err))
 	}
@@ -1069,7 +1023,7 @@
 		lg.Panic("failed to restore v2 store", zap.Error(err))
 	}
 
-	if err := assertNoV2StoreContent(lg, s.v2store, s.Cfg.V2Deprecation); err != nil {
+	if err := serverstorage.AssertNoV2StoreContent(lg, s.v2store, s.Cfg.V2Deprecation); err != nil {
 		lg.Panic("illegal v2store content", zap.Error(err))
 	}
 
diff --git a/server/etcdserver/server_test.go b/server/etcdserver/server_test.go
index 4f2e5d0..4524cd8 100644
--- a/server/etcdserver/server_test.go
+++ b/server/etcdserver/server_test.go
@@ -51,6 +51,7 @@
 	"go.etcd.io/etcd/server/v3/mock/mockstorage"
 	"go.etcd.io/etcd/server/v3/mock/mockstore"
 	"go.etcd.io/etcd/server/v3/mock/mockwait"
+	serverstorage "go.etcd.io/etcd/server/v3/storage"
 	betesting "go.etcd.io/etcd/server/v3/storage/backend/testing"
 	"go.etcd.io/etcd/server/v3/storage/mvcc"
 	"go.etcd.io/etcd/server/v3/storage/schema"
@@ -614,7 +615,7 @@
 		id:      1,
 		r:       *r,
 		cluster: cl,
-		beHooks: &backendHooks{lg: lg},
+		beHooks: serverstorage.NewBackendHooks(lg, nil),
 	}
 	cc := raftpb.ConfChange{
 		Type:   raftpb.ConfChangeRemoveNode,
@@ -662,7 +663,7 @@
 		cluster:      cl,
 		w:            wait.New(),
 		consistIndex: ci,
-		beHooks:      &backendHooks{lg: lg, indexer: ci},
+		beHooks:      serverstorage.NewBackendHooks(lg, ci),
 	}
 
 	// create EntryConfChange entry
@@ -746,7 +747,7 @@
 		cluster:      cl,
 		w:            wait.New(),
 		consistIndex: ci,
-		beHooks:      &backendHooks{lg: lg, indexer: ci},
+		beHooks:      serverstorage.NewBackendHooks(lg, ci),
 	}
 	ents := []raftpb.Entry{}
 	for i := 1; i <= 4; i++ {
@@ -1120,7 +1121,7 @@
 		cluster:      cl,
 		SyncTicker:   &time.Ticker{},
 		consistIndex: ci,
-		beHooks:      &backendHooks{lg: lg, indexer: ci},
+		beHooks:      serverstorage.NewBackendHooks(lg, ci),
 	}
 	s.applyV2 = &applierV2store{store: s.v2store, cluster: s.cluster}
 
@@ -1273,7 +1274,7 @@
 		cluster:      cl,
 		SyncTicker:   &time.Ticker{},
 		consistIndex: ci,
-		beHooks:      &backendHooks{lg: lg, indexer: ci},
+		beHooks:      serverstorage.NewBackendHooks(lg, ci),
 	}
 	s.applyV2 = &applierV2store{store: s.v2store, cluster: s.cluster}
 
@@ -1358,7 +1359,7 @@
 		reqIDGen:     idutil.NewGenerator(0, time.Time{}),
 		SyncTicker:   &time.Ticker{},
 		consistIndex: cindex.NewFakeConsistentIndex(0),
-		beHooks:      &backendHooks{lg: lg},
+		beHooks:      serverstorage.NewBackendHooks(lg, nil),
 	}
 	s.start()
 	m := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"foo"}}}
@@ -1405,7 +1406,7 @@
 		reqIDGen:     idutil.NewGenerator(0, time.Time{}),
 		SyncTicker:   &time.Ticker{},
 		consistIndex: cindex.NewFakeConsistentIndex(0),
-		beHooks:      &backendHooks{lg: lg},
+		beHooks:      serverstorage.NewBackendHooks(lg, nil),
 	}
 	s.start()
 	_, err := s.RemoveMember(context.Background(), 1234)
@@ -1451,7 +1452,7 @@
 		reqIDGen:     idutil.NewGenerator(0, time.Time{}),
 		SyncTicker:   &time.Ticker{},
 		consistIndex: cindex.NewFakeConsistentIndex(0),
-		beHooks:      &backendHooks{lg: lg},
+		beHooks:      serverstorage.NewBackendHooks(lg, nil),
 	}
 	s.start()
 	wm := membership.Member{ID: 1234, RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://127.0.0.1:1"}}}
diff --git a/server/etcdserver/storage.go b/server/etcdserver/storage.go
index 24e0c6d..8170c29 100644
--- a/server/etcdserver/storage.go
+++ b/server/etcdserver/storage.go
@@ -17,8 +17,8 @@
 import (
 	"go.etcd.io/etcd/raft/v3/raftpb"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 )
 
 type Storage interface {
diff --git a/server/go.mod b/server/go.mod
index 41c9eab..9335e15 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -6,8 +6,8 @@
 	github.com/coreos/go-semver v0.3.0
 	github.com/coreos/go-systemd/v22 v22.3.2
 	github.com/dustin/go-humanize v1.0.0
-	github.com/form3tech-oss/jwt-go v3.2.3+incompatible
 	github.com/gogo/protobuf v1.3.2
+	github.com/golang-jwt/jwt v3.2.2+incompatible
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
 	github.com/golang/protobuf v1.5.2
 	github.com/google/btree v1.0.1
@@ -42,6 +42,7 @@
 	golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
 	google.golang.org/grpc v1.38.0
+	google.golang.org/protobuf v1.26.0
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/server/go.sum b/server/go.sum
index 1af3315..101443f 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -76,8 +76,6 @@
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -96,6 +94,8 @@
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
diff --git a/server/etcdserver/backend.go b/server/storage/backend.go
similarity index 82%
rename from server/etcdserver/backend.go
rename to server/storage/backend.go
index e0da65c..abbbf88 100644
--- a/server/etcdserver/backend.go
+++ b/server/storage/backend.go
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package etcdserver
+package storage
 
 import (
 	"fmt"
@@ -55,8 +55,8 @@
 	return backend.New(bcfg)
 }
 
-// openSnapshotBackend renames a snapshot db to the current etcd db and opens it.
-func openSnapshotBackend(cfg config.ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot, hooks backend.Hooks) (backend.Backend, error) {
+// OpenSnapshotBackend renames a snapshot db to the current etcd db and opens it.
+func OpenSnapshotBackend(cfg config.ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot, hooks *BackendHooks) (backend.Backend, error) {
 	snapPath, err := ss.DBFilePath(snapshot.Metadata.Index)
 	if err != nil {
 		return nil, fmt.Errorf("failed to find database snapshot file (%v)", err)
@@ -64,11 +64,11 @@
 	if err := os.Rename(snapPath, cfg.BackendPath()); err != nil {
 		return nil, fmt.Errorf("failed to rename database snapshot file (%v)", err)
 	}
-	return openBackend(cfg, hooks), nil
+	return OpenBackend(cfg, hooks), nil
 }
 
-// openBackend returns a backend using the current etcd db.
-func openBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend {
+// OpenBackend returns a backend using the current etcd db.
+func OpenBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend {
 	fn := cfg.BackendPath()
 
 	now, beOpened := time.Now(), make(chan backend.Backend)
@@ -92,11 +92,11 @@
 	return <-beOpened
 }
 
-// recoverBackendSnapshot recovers the DB from a snapshot in case etcd crashes
+// RecoverSnapshotBackend recovers the DB from a snapshot in case etcd crashes
 // before updating the backend db after persisting raft snapshot to disk,
 // violating the invariant snapshot.Metadata.Index < db.consistentIndex. In this
 // case, replace the db with the snapshot db sent by the leader.
-func recoverSnapshotBackend(cfg config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks backend.Hooks) (backend.Backend, error) {
+func RecoverSnapshotBackend(cfg config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks *BackendHooks) (backend.Backend, error) {
 	consistentIndex := uint64(0)
 	if beExist {
 		consistentIndex, _ = schema.ReadConsistentIndex(oldbe.BatchTx())
@@ -105,5 +105,5 @@
 		return oldbe, nil
 	}
 	oldbe.Close()
-	return openSnapshotBackend(cfg, snap.New(cfg.Logger, cfg.SnapDir()), snapshot, hooks)
+	return OpenSnapshotBackend(cfg, snap.New(cfg.Logger, cfg.SnapDir()), snapshot, hooks)
 }
diff --git a/server/datadir/datadir.go b/server/storage/datadir/datadir.go
similarity index 100%
rename from server/datadir/datadir.go
rename to server/storage/datadir/datadir.go
diff --git a/server/datadir/datadir_test.go b/server/storage/datadir/datadir_test.go
similarity index 94%
rename from server/datadir/datadir_test.go
rename to server/storage/datadir/datadir_test.go
index f6fe19b..3933839 100644
--- a/server/datadir/datadir_test.go
+++ b/server/storage/datadir/datadir_test.go
@@ -4,7 +4,7 @@
 	"testing"
 
 	"github.com/stretchr/testify/assert"
-	"go.etcd.io/etcd/server/v3/datadir"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 )
 
 func TestToBackendFileName(t *testing.T) {
diff --git a/server/datadir/doc.go b/server/storage/datadir/doc.go
similarity index 100%
rename from server/datadir/doc.go
rename to server/storage/datadir/doc.go
diff --git a/server/storage/hooks.go b/server/storage/hooks.go
new file mode 100644
index 0000000..e9a9f25
--- /dev/null
+++ b/server/storage/hooks.go
@@ -0,0 +1,60 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+	"sync"
+
+	"go.uber.org/zap"
+
+	"go.etcd.io/etcd/raft/v3/raftpb"
+	"go.etcd.io/etcd/server/v3/etcdserver/cindex"
+	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/schema"
+)
+
+type BackendHooks struct {
+	indexer cindex.ConsistentIndexer
+	lg      *zap.Logger
+
+	// confState to Be written in the next submitted Backend transaction (if dirty)
+	confState raftpb.ConfState
+	// first write changes it to 'dirty'. false by default, so
+	// not initialized `confState` is meaningless.
+	confStateDirty bool
+	confStateLock  sync.Mutex
+}
+
+func NewBackendHooks(lg *zap.Logger, indexer cindex.ConsistentIndexer) *BackendHooks {
+	return &BackendHooks{lg: lg, indexer: indexer}
+}
+
+func (bh *BackendHooks) OnPreCommitUnsafe(tx backend.BatchTx) {
+	bh.indexer.UnsafeSave(tx)
+	bh.confStateLock.Lock()
+	defer bh.confStateLock.Unlock()
+	if bh.confStateDirty {
+		schema.MustUnsafeSaveConfStateToBackend(bh.lg, tx, &bh.confState)
+		// save bh.confState
+		bh.confStateDirty = false
+	}
+}
+
+func (bh *BackendHooks) SetConfState(confState *raftpb.ConfState) {
+	bh.confStateLock.Lock()
+	defer bh.confStateLock.Unlock()
+	bh.confState = *confState
+	bh.confStateDirty = true
+}
diff --git a/server/storage/metrics.go b/server/storage/metrics.go
new file mode 100644
index 0000000..cb7f870
--- /dev/null
+++ b/server/storage/metrics.go
@@ -0,0 +1,30 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+var quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{
+	Namespace: "etcd",
+	Subsystem: "server",
+	Name:      "quota_backend_bytes",
+	Help:      "Current backend storage quota size in bytes.",
+})
+
+func init() {
+	prometheus.MustRegister(quotaBackendBytes)
+}
diff --git a/server/storage/mvcc/metrics_txn.go b/server/storage/mvcc/metrics_txn.go
index af844f8..aef877a 100644
--- a/server/storage/mvcc/metrics_txn.go
+++ b/server/storage/mvcc/metrics_txn.go
@@ -61,7 +61,6 @@
 
 	ranges := float64(tw.ranges)
 	rangeCounter.Add(ranges)
-	rangeCounterDebug.Add(ranges) // TODO: remove in 3.5 release
 
 	puts := float64(tw.puts)
 	putCounter.Add(puts)
diff --git a/server/etcdserver/quota.go b/server/storage/quota.go
similarity index 75%
rename from server/etcdserver/quota.go
rename to server/storage/quota.go
index 33c06e6..e15079d 100644
--- a/server/etcdserver/quota.go
+++ b/server/storage/quota.go
@@ -12,12 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package etcdserver
+package storage
 
 import (
 	"sync"
 
 	pb "go.etcd.io/etcd/api/v3/etcdserverpb"
+	"go.etcd.io/etcd/server/v3/config"
+	"go.etcd.io/etcd/server/v3/storage/backend"
 
 	humanize "github.com/dustin/go-humanize"
 	"go.uber.org/zap"
@@ -50,15 +52,15 @@
 func (*passthroughQuota) Cost(interface{}) int       { return 0 }
 func (*passthroughQuota) Remaining() int64           { return 1 }
 
-type backendQuota struct {
-	s               *EtcdServer
+type BackendQuota struct {
+	be              backend.Backend
 	maxBackendBytes int64
 }
 
 const (
 	// leaseOverhead is an estimate for the cost of storing a lease
 	leaseOverhead = 64
-	// kvOverhead is an estimate for the cost of storing a key's metadata
+	// kvOverhead is an estimate for the cost of storing a key's Metadata
 	kvOverhead = 256
 )
 
@@ -71,23 +73,23 @@
 )
 
 // NewBackendQuota creates a quota layer with the given storage limit.
-func NewBackendQuota(s *EtcdServer, name string) Quota {
-	lg := s.Logger()
-	quotaBackendBytes.Set(float64(s.Cfg.QuotaBackendBytes))
+func NewBackendQuota(cfg config.ServerConfig, be backend.Backend, name string) Quota {
+	lg := cfg.Logger
+	quotaBackendBytes.Set(float64(cfg.QuotaBackendBytes))
 
-	if s.Cfg.QuotaBackendBytes < 0 {
+	if cfg.QuotaBackendBytes < 0 {
 		// disable quotas if negative
 		quotaLogOnce.Do(func() {
 			lg.Info(
 				"disabled backend quota",
 				zap.String("quota-name", name),
-				zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
+				zap.Int64("quota-size-bytes", cfg.QuotaBackendBytes),
 			)
 		})
 		return &passthroughQuota{}
 	}
 
-	if s.Cfg.QuotaBackendBytes == 0 {
+	if cfg.QuotaBackendBytes == 0 {
 		// use default size if no quota size given
 		quotaLogOnce.Do(func() {
 			if lg != nil {
@@ -100,16 +102,16 @@
 			}
 		})
 		quotaBackendBytes.Set(float64(DefaultQuotaBytes))
-		return &backendQuota{s, DefaultQuotaBytes}
+		return &BackendQuota{be, DefaultQuotaBytes}
 	}
 
 	quotaLogOnce.Do(func() {
-		if s.Cfg.QuotaBackendBytes > MaxQuotaBytes {
+		if cfg.QuotaBackendBytes > MaxQuotaBytes {
 			lg.Warn(
 				"quota exceeds the maximum value",
 				zap.String("quota-name", name),
-				zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
-				zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))),
+				zap.Int64("quota-size-bytes", cfg.QuotaBackendBytes),
+				zap.String("quota-size", humanize.Bytes(uint64(cfg.QuotaBackendBytes))),
 				zap.Int64("quota-maximum-size-bytes", MaxQuotaBytes),
 				zap.String("quota-maximum-size", maxQuotaSize),
 			)
@@ -117,19 +119,19 @@
 		lg.Info(
 			"enabled backend quota",
 			zap.String("quota-name", name),
-			zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes),
-			zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))),
+			zap.Int64("quota-size-bytes", cfg.QuotaBackendBytes),
+			zap.String("quota-size", humanize.Bytes(uint64(cfg.QuotaBackendBytes))),
 		)
 	})
-	return &backendQuota{s, s.Cfg.QuotaBackendBytes}
+	return &BackendQuota{be, cfg.QuotaBackendBytes}
 }
 
-func (b *backendQuota) Available(v interface{}) bool {
-	// TODO: maybe optimize backend.Size()
-	return b.s.Backend().Size()+int64(b.Cost(v)) < b.maxBackendBytes
+func (b *BackendQuota) Available(v interface{}) bool {
+	// TODO: maybe optimize Backend.Size()
+	return b.be.Size()+int64(b.Cost(v)) < b.maxBackendBytes
 }
 
-func (b *backendQuota) Cost(v interface{}) int {
+func (b *BackendQuota) Cost(v interface{}) int {
 	switch r := v.(type) {
 	case *pb.PutRequest:
 		return costPut(r)
@@ -167,6 +169,6 @@
 	return sizeSuccess
 }
 
-func (b *backendQuota) Remaining() int64 {
-	return b.maxBackendBytes - b.s.Backend().Size()
+func (b *BackendQuota) Remaining() int64 {
+	return b.maxBackendBytes - b.be.Size()
 }
diff --git a/server/storage/schema/schema.go b/server/storage/schema/schema.go
index 12f8c3c..7750e11 100644
--- a/server/storage/schema/schema.go
+++ b/server/storage/schema/schema.go
@@ -32,7 +32,7 @@
 func UpdateStorageSchema(lg *zap.Logger, tx backend.BatchTx) error {
 	tx.Lock()
 	defer tx.Unlock()
-	v, err := detectStorageVersion(lg, tx)
+	v, err := DetectSchemaVersion(lg, tx)
 	if err != nil {
 		return fmt.Errorf("cannot determine storage version: %w", err)
 	}
@@ -48,7 +48,7 @@
 	return nil
 }
 
-func detectStorageVersion(lg *zap.Logger, tx backend.ReadTx) (*semver.Version, error) {
+func DetectSchemaVersion(lg *zap.Logger, tx backend.ReadTx) (*semver.Version, error) {
 	v := UnsafeReadStorageVersion(tx)
 	if v != nil {
 		return v, nil
diff --git a/server/storage/schema/version.go b/server/storage/schema/version.go
index 4b8738a..341b386 100644
--- a/server/storage/schema/version.go
+++ b/server/storage/schema/version.go
@@ -59,3 +59,8 @@
 	sv := semver.Version{Major: v.Major, Minor: v.Minor}
 	tx.UnsafePut(Meta, MetaStorageVersionName, []byte(sv.String()))
 }
+
+// UnsafeClearStorageVersion removes etcd storage version in backend.
+func UnsafeClearStorageVersion(tx backend.BatchTx) {
+	tx.UnsafeDelete(Meta, MetaStorageVersionName)
+}
diff --git a/server/storage/schema/wal.go b/server/storage/schema/wal.go
new file mode 100644
index 0000000..aef7e84
--- /dev/null
+++ b/server/storage/schema/wal.go
@@ -0,0 +1,158 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package schema
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/coreos/go-semver/semver"
+	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/types/descriptorpb"
+
+	"go.etcd.io/etcd/api/v3/etcdserverpb"
+	"go.etcd.io/etcd/pkg/v3/pbutil"
+	"go.etcd.io/etcd/raft/v3/raftpb"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+)
+
+// MinimalStorageVersionFromWAL returns minimal etcd storage able to interpret provided WAL log,
+// determined by looking at entries since the last snapshot and returning the highest
+// etcd version annotation from used messages, fields, enums and their values.
+func MinimalStorageVersionFromWAL(wal *wal.WAL) *semver.Version {
+	_, _, ents, err := wal.ReadAll()
+	if err != nil {
+		panic(err)
+	}
+	var maxVer *semver.Version
+	for _, ent := range ents {
+		maxVer = maxVersion(maxVer, etcdVersionFromEntry(ent))
+	}
+	return maxVer
+}
+
+func etcdVersionFromEntry(ent raftpb.Entry) *semver.Version {
+	msgVer := etcdVersionFromMessage(proto.MessageReflect(&ent))
+	dataVer := etcdVersionFromData(ent.Type, ent.Data)
+	return maxVersion(msgVer, dataVer)
+}
+
+func etcdVersionFromData(entryType raftpb.EntryType, data []byte) *semver.Version {
+	var msg protoreflect.Message
+	switch entryType {
+	case raftpb.EntryNormal:
+		var raftReq etcdserverpb.InternalRaftRequest
+		err := pbutil.Unmarshaler(&raftReq).Unmarshal(data)
+		if err != nil {
+			return nil
+		}
+		msg = proto.MessageReflect(&raftReq)
+	case raftpb.EntryConfChange:
+		var confChange raftpb.ConfChange
+		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
+		if err != nil {
+			return nil
+		}
+		msg = proto.MessageReflect(&confChange)
+	case raftpb.EntryConfChangeV2:
+		var confChange raftpb.ConfChangeV2
+		err := pbutil.Unmarshaler(&confChange).Unmarshal(data)
+		if err != nil {
+			return nil
+		}
+		msg = proto.MessageReflect(&confChange)
+	default:
+		panic("unhandled")
+	}
+	return etcdVersionFromMessage(msg)
+}
+
+func etcdVersionFromMessage(m protoreflect.Message) *semver.Version {
+	var maxVer *semver.Version
+	md := m.Descriptor()
+	opts := md.Options().(*descriptorpb.MessageOptions)
+	if opts != nil {
+		maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(opts.String()))
+	}
+
+	m.Range(func(field protoreflect.FieldDescriptor, value protoreflect.Value) bool {
+		fd := md.Fields().Get(field.Index())
+		maxVer = maxVersion(maxVer, etcdVersionFromField(fd))
+		switch m := value.Interface().(type) {
+		case protoreflect.Message:
+			maxVer = maxVersion(maxVer, etcdVersionFromMessage(m))
+		case protoreflect.EnumNumber:
+			maxVer = maxVersion(maxVer, etcdVersionFromEnum(field.Enum(), m))
+		}
+		return true
+	})
+	return maxVer
+}
+
+func etcdVersionFromEnum(enum protoreflect.EnumDescriptor, value protoreflect.EnumNumber) *semver.Version {
+	var maxVer *semver.Version
+	enumOpts := enum.Options().(*descriptorpb.EnumOptions)
+	if enumOpts != nil {
+		maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(enumOpts.String()))
+	}
+	valueDesc := enum.Values().Get(int(value))
+	valueOpts := valueDesc.Options().(*descriptorpb.EnumValueOptions)
+	if valueOpts != nil {
+		maxVer = maxVersion(maxVer, etcdVersionFromOptionsString(valueOpts.String()))
+	}
+	return maxVer
+}
+
+func maxVersion(a *semver.Version, b *semver.Version) *semver.Version {
+	if a != nil && (b == nil || b.LessThan(*a)) {
+		return a
+	}
+	return b
+}
+
+func etcdVersionFromField(fd protoreflect.FieldDescriptor) *semver.Version {
+	opts := fd.Options().(*descriptorpb.FieldOptions)
+	if opts == nil {
+		return nil
+	}
+	return etcdVersionFromOptionsString(opts.String())
+}
+
+func etcdVersionFromOptionsString(opts string) *semver.Version {
+	// TODO: Use proto.GetExtention when gogo/protobuf is usable with protoreflect
+	msgs := []string{"[versionpb.etcd_version_msg]:", "[versionpb.etcd_version_field]:", "[versionpb.etcd_version_enum]:", "[versionpb.etcd_version_enum_value]:"}
+	var end, index int
+	for _, msg := range msgs {
+		index = strings.Index(opts, msg)
+		end = index + len(msg)
+		if index != -1 {
+			break
+		}
+	}
+	if index == -1 {
+		return nil
+	}
+	var verStr string
+	_, err := fmt.Sscanf(opts[end:], "%q", &verStr)
+	if err != nil {
+		return nil
+	}
+	ver, err := semver.NewVersion(verStr + ".0")
+	if err != nil {
+		panic(err)
+	}
+	return ver
+}
diff --git a/server/storage/schema/wal_test.go b/server/storage/schema/wal_test.go
new file mode 100644
index 0000000..423ce2a
--- /dev/null
+++ b/server/storage/schema/wal_test.go
@@ -0,0 +1,268 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package schema
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/coreos/go-semver/semver"
+	"github.com/golang/protobuf/proto"
+	"github.com/stretchr/testify/assert"
+
+	"go.etcd.io/etcd/api/v3/etcdserverpb"
+	"go.etcd.io/etcd/api/v3/membershippb"
+	"go.etcd.io/etcd/pkg/v3/pbutil"
+	"go.etcd.io/etcd/raft/v3/raftpb"
+)
+
+var (
+	V3_0 = semver.Version{Major: 3, Minor: 0}
+	V3_1 = semver.Version{Major: 3, Minor: 1}
+	V3_3 = semver.Version{Major: 3, Minor: 3}
+	V3_4 = semver.Version{Major: 3, Minor: 4}
+)
+
+func TestEtcdVersionFromEntry(t *testing.T) {
+	raftReq := etcdserverpb.InternalRaftRequest{Header: &etcdserverpb.RequestHeader{AuthRevision: 1}}
+	normalRequestData := pbutil.MustMarshal(&raftReq)
+
+	confChange := raftpb.ConfChange{Type: raftpb.ConfChangeAddLearnerNode}
+	confChangeData := pbutil.MustMarshal(&confChange)
+
+	confChangeV2 := raftpb.ConfChangeV2{Transition: raftpb.ConfChangeTransitionJointExplicit}
+	confChangeV2Data := pbutil.MustMarshal(&confChangeV2)
+
+	tcs := []struct {
+		name   string
+		input  raftpb.Entry
+		expect *semver.Version
+	}{
+		{
+			name: "Using RequestHeader AuthRevision in NormalEntry implies v3.1",
+			input: raftpb.Entry{
+				Term:  1,
+				Index: 2,
+				Type:  raftpb.EntryNormal,
+				Data:  normalRequestData,
+			},
+			expect: &V3_1,
+		},
+		{
+			name: "Using ConfigChange implies v3.4",
+			input: raftpb.Entry{
+				Term:  1,
+				Index: 2,
+				Type:  raftpb.EntryConfChange,
+				Data:  confChangeData,
+			},
+			expect: &V3_0,
+		},
+		{
+			name: "Using ConfigChangeV2 implies v3.4",
+			input: raftpb.Entry{
+				Term:  1,
+				Index: 2,
+				Type:  raftpb.EntryConfChangeV2,
+				Data:  confChangeV2Data,
+			},
+			expect: &V3_4,
+		},
+	}
+	for _, tc := range tcs {
+		t.Run(tc.name, func(t *testing.T) {
+			ver := etcdVersionFromEntry(tc.input)
+			assert.Equal(t, tc.expect, ver)
+		})
+	}
+}
+
+func TestEtcdVersionFromMessage(t *testing.T) {
+	tcs := []struct {
+		name   string
+		input  proto.Message
+		expect *semver.Version
+	}{
+		{
+			name:   "Empty RequestHeader impies v3.0",
+			input:  &etcdserverpb.RequestHeader{},
+			expect: &V3_0,
+		},
+		{
+			name:   "RequestHeader AuthRevision field set implies v3.5",
+			input:  &etcdserverpb.RequestHeader{AuthRevision: 1},
+			expect: &V3_1,
+		},
+		{
+			name:   "RequestHeader Username set implies v3.0",
+			input:  &etcdserverpb.RequestHeader{Username: "Alice"},
+			expect: &V3_0,
+		},
+		{
+			name:   "When two fields are set take higher version",
+			input:  &etcdserverpb.RequestHeader{AuthRevision: 1, Username: "Alice"},
+			expect: &V3_1,
+		},
+		{
+			name:   "Setting a RequestHeader AuthRevision in subfield implies v3.1",
+			input:  &etcdserverpb.InternalRaftRequest{Header: &etcdserverpb.RequestHeader{AuthRevision: 1}},
+			expect: &V3_1,
+		},
+		{
+			name:   "Setting a DowngradeInfoSetRequest implies v3.5",
+			input:  &etcdserverpb.InternalRaftRequest{DowngradeInfoSet: &membershippb.DowngradeInfoSetRequest{}},
+			expect: &V3_5,
+		},
+		{
+			name:   "Enum CompareResult set to EQUAL implies v3.0",
+			input:  &etcdserverpb.Compare{Result: etcdserverpb.Compare_EQUAL},
+			expect: &V3_0,
+		},
+		{
+			name:   "Enum CompareResult set to NOT_EQUAL implies v3.1",
+			input:  &etcdserverpb.Compare{Result: etcdserverpb.Compare_NOT_EQUAL},
+			expect: &V3_1,
+		},
+		{
+			name:   "Oneof Compare version set implies v3.1",
+			input:  &etcdserverpb.Compare{TargetUnion: &etcdserverpb.Compare_Version{}},
+			expect: &V3_0,
+		},
+		{
+			name:   "Oneof Compare lease set implies v3.3",
+			input:  &etcdserverpb.Compare{TargetUnion: &etcdserverpb.Compare_Lease{}},
+			expect: &V3_3,
+		},
+	}
+	for _, tc := range tcs {
+		t.Run(tc.name, func(t *testing.T) {
+			ver := etcdVersionFromMessage(proto.MessageReflect(tc.input))
+			assert.Equal(t, tc.expect, ver)
+		})
+	}
+}
+
+func TestEtcdVersionFromFieldOptionsString(t *testing.T) {
+	tcs := []struct {
+		input  string
+		expect *semver.Version
+	}{
+		{
+			input: "65001:0",
+		},
+		{
+			input: `65001:0  65004:"NodeID"`,
+		},
+		{
+			input: `[versionpb.XXX]:"3.5"`,
+		},
+		{
+			input:  `[versionpb.etcd_version_msg]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_enum]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_field]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_enum_value]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `65001:0 [versionpb.etcd_version_msg]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `65004:"NodeID" [versionpb.etcd_version_msg]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `65004:"NodeID" [versionpb.etcd_version_enum]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.other_field]:"NodeID" [versionpb.etcd_version_msg]:"3.5"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_msg]:"3.5" 65001:0`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_msg]:"3.5" 65004:"NodeID"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.etcd_version_msg]:"3.5" [versionpb.other_field]:"NodeID"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `[versionpb.other_field]:"NodeID" [versionpb.etcd_version_msg]:"3.5" [versionpb.another_field]:"NodeID"`,
+			expect: &V3_5,
+		},
+		{
+			input:  `65001:0 [versionpb.etcd_version_msg]:"3.5" 65001:0"`,
+			expect: &V3_5,
+		},
+	}
+	for _, tc := range tcs {
+		t.Run(tc.input, func(t *testing.T) {
+			ver := etcdVersionFromOptionsString(tc.input)
+			assert.Equal(t, ver, tc.expect)
+		})
+	}
+}
+
+func TestMaxVersion(t *testing.T) {
+	tcs := []struct {
+		a, b, expect *semver.Version
+	}{
+		{
+			a:      nil,
+			b:      nil,
+			expect: nil,
+		},
+		{
+			a:      &V3_5,
+			b:      nil,
+			expect: &V3_5,
+		},
+		{
+			a:      nil,
+			b:      &V3_5,
+			expect: &V3_5,
+		},
+		{
+			a:      &V3_6,
+			b:      &V3_5,
+			expect: &V3_6,
+		},
+		{
+			a:      &V3_5,
+			b:      &V3_6,
+			expect: &V3_6,
+		},
+	}
+	for _, tc := range tcs {
+		t.Run(fmt.Sprintf("%v %v %v", tc.a, tc.b, tc.expect), func(t *testing.T) {
+			got := maxVersion(tc.a, tc.b)
+			assert.Equal(t, got, tc.expect)
+		})
+	}
+}
diff --git a/server/storage/util.go b/server/storage/util.go
new file mode 100644
index 0000000..bdac72e
--- /dev/null
+++ b/server/storage/util.go
@@ -0,0 +1,150 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+	"encoding/json"
+	"fmt"
+	"sort"
+
+	"go.uber.org/zap"
+
+	"go.etcd.io/etcd/client/pkg/v3/types"
+	"go.etcd.io/etcd/pkg/v3/pbutil"
+	"go.etcd.io/etcd/raft/v3/raftpb"
+	"go.etcd.io/etcd/server/v3/config"
+	"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
+	"go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
+)
+
+// AssertNoV2StoreContent -> depending on the deprecation stage, warns or report an error
+// if the v2store contains custom content.
+func AssertNoV2StoreContent(lg *zap.Logger, st v2store.Store, deprecationStage config.V2DeprecationEnum) error {
+	metaOnly, err := membership.IsMetaStoreOnly(st)
+	if err != nil {
+		return err
+	}
+	if metaOnly {
+		return nil
+	}
+	if deprecationStage.IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) {
+		return fmt.Errorf("detected disallowed custom content in v2store for stage --v2-deprecation=%s", deprecationStage)
+	}
+	lg.Warn("detected custom v2store content. Etcd v3.5 is the last version allowing to access it using API v2. Please remove the content.")
+	return nil
+}
+
+// CreateConfigChangeEnts creates a series of Raft entries (i.e.
+// EntryConfChange) to remove the set of given IDs from the cluster. The ID
+// `self` is _not_ removed, even if present in the set.
+// If `self` is not inside the given ids, it creates a Raft entry to add a
+// default member with the given `self`.
+func CreateConfigChangeEnts(lg *zap.Logger, ids []uint64, self uint64, term, index uint64) []raftpb.Entry {
+	found := false
+	for _, id := range ids {
+		if id == self {
+			found = true
+		}
+	}
+
+	var ents []raftpb.Entry
+	next := index + 1
+
+	// NB: always add self first, then remove other nodes. Raft will panic if the
+	// set of voters ever becomes empty.
+	if !found {
+		m := membership.Member{
+			ID:             types.ID(self),
+			RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:2380"}},
+		}
+		ctx, err := json.Marshal(m)
+		if err != nil {
+			lg.Panic("failed to marshal member", zap.Error(err))
+		}
+		cc := &raftpb.ConfChange{
+			Type:    raftpb.ConfChangeAddNode,
+			NodeID:  self,
+			Context: ctx,
+		}
+		e := raftpb.Entry{
+			Type:  raftpb.EntryConfChange,
+			Data:  pbutil.MustMarshal(cc),
+			Term:  term,
+			Index: next,
+		}
+		ents = append(ents, e)
+		next++
+	}
+
+	for _, id := range ids {
+		if id == self {
+			continue
+		}
+		cc := &raftpb.ConfChange{
+			Type:   raftpb.ConfChangeRemoveNode,
+			NodeID: id,
+		}
+		e := raftpb.Entry{
+			Type:  raftpb.EntryConfChange,
+			Data:  pbutil.MustMarshal(cc),
+			Term:  term,
+			Index: next,
+		}
+		ents = append(ents, e)
+		next++
+	}
+
+	return ents
+}
+
+// GetIDs returns an ordered set of IDs included in the given snapshot and
+// the entries. The given snapshot/entries can contain three kinds of
+// ID-related entry:
+// - ConfChangeAddNode, in which case the contained ID will Be added into the set.
+// - ConfChangeRemoveNode, in which case the contained ID will Be removed from the set.
+// - ConfChangeAddLearnerNode, in which the contained ID will Be added into the set.
+func GetIDs(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 {
+	ids := make(map[uint64]bool)
+	if snap != nil {
+		for _, id := range snap.Metadata.ConfState.Voters {
+			ids[id] = true
+		}
+	}
+	for _, e := range ents {
+		if e.Type != raftpb.EntryConfChange {
+			continue
+		}
+		var cc raftpb.ConfChange
+		pbutil.MustUnmarshal(&cc, e.Data)
+		switch cc.Type {
+		case raftpb.ConfChangeAddLearnerNode:
+			ids[cc.NodeID] = true
+		case raftpb.ConfChangeAddNode:
+			ids[cc.NodeID] = true
+		case raftpb.ConfChangeRemoveNode:
+			delete(ids, cc.NodeID)
+		case raftpb.ConfChangeUpdateNode:
+			// do nothing
+		default:
+			lg.Panic("unknown ConfChange Type", zap.String("type", cc.Type.String()))
+		}
+	}
+	sids := make(types.Uint64Slice, 0, len(ids))
+	for id := range ids {
+		sids = append(sids, id)
+	}
+	sort.Sort(sids)
+	return []uint64(sids)
+}
diff --git a/server/wal/decoder.go b/server/storage/wal/decoder.go
similarity index 98%
rename from server/wal/decoder.go
rename to server/storage/wal/decoder.go
index 0251a72..7cc634a 100644
--- a/server/wal/decoder.go
+++ b/server/storage/wal/decoder.go
@@ -24,7 +24,7 @@
 	"go.etcd.io/etcd/pkg/v3/crc"
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 )
 
 const minSectorSize = 512
diff --git a/server/wal/doc.go b/server/storage/wal/doc.go
similarity index 100%
rename from server/wal/doc.go
rename to server/storage/wal/doc.go
diff --git a/server/wal/encoder.go b/server/storage/wal/encoder.go
similarity index 98%
rename from server/wal/encoder.go
rename to server/storage/wal/encoder.go
index 61b4c20..d9e221f 100644
--- a/server/wal/encoder.go
+++ b/server/storage/wal/encoder.go
@@ -23,7 +23,7 @@
 
 	"go.etcd.io/etcd/pkg/v3/crc"
 	"go.etcd.io/etcd/pkg/v3/ioutil"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 )
 
 // walPageBytes is the alignment for flushing records to the backing Writer.
diff --git a/server/wal/file_pipeline.go b/server/storage/wal/file_pipeline.go
similarity index 100%
rename from server/wal/file_pipeline.go
rename to server/storage/wal/file_pipeline.go
diff --git a/server/wal/file_pipeline_test.go b/server/storage/wal/file_pipeline_test.go
similarity index 100%
rename from server/wal/file_pipeline_test.go
rename to server/storage/wal/file_pipeline_test.go
diff --git a/server/wal/metrics.go b/server/storage/wal/metrics.go
similarity index 100%
rename from server/wal/metrics.go
rename to server/storage/wal/metrics.go
diff --git a/server/wal/record_test.go b/server/storage/wal/record_test.go
similarity index 97%
rename from server/wal/record_test.go
rename to server/storage/wal/record_test.go
index d28807e..1de390d 100644
--- a/server/wal/record_test.go
+++ b/server/storage/wal/record_test.go
@@ -23,7 +23,7 @@
 	"reflect"
 	"testing"
 
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 )
 
 var (
diff --git a/server/wal/repair.go b/server/storage/wal/repair.go
similarity index 98%
rename from server/wal/repair.go
rename to server/storage/wal/repair.go
index 122ee49..b6b9b49 100644
--- a/server/wal/repair.go
+++ b/server/storage/wal/repair.go
@@ -21,7 +21,7 @@
 	"time"
 
 	"go.etcd.io/etcd/client/pkg/v3/fileutil"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.uber.org/zap"
 )
 
diff --git a/server/wal/repair_test.go b/server/storage/wal/repair_test.go
similarity index 98%
rename from server/wal/repair_test.go
rename to server/storage/wal/repair_test.go
index e2e3294..089d5a7 100644
--- a/server/wal/repair_test.go
+++ b/server/storage/wal/repair_test.go
@@ -22,7 +22,7 @@
 	"testing"
 
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 
 	"go.uber.org/zap"
 )
diff --git a/server/wal/util.go b/server/storage/wal/util.go
similarity index 100%
rename from server/wal/util.go
rename to server/storage/wal/util.go
diff --git a/server/wal/wal.go b/server/storage/wal/wal.go
similarity index 99%
rename from server/wal/wal.go
rename to server/storage/wal/wal.go
index 3c940e0..83c10d4 100644
--- a/server/wal/wal.go
+++ b/server/storage/wal/wal.go
@@ -30,7 +30,7 @@
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 
 	"go.uber.org/zap"
 )
diff --git a/server/wal/wal_bench_test.go b/server/storage/wal/wal_bench_test.go
similarity index 100%
rename from server/wal/wal_bench_test.go
rename to server/storage/wal/wal_bench_test.go
diff --git a/server/wal/wal_test.go b/server/storage/wal/wal_test.go
similarity index 99%
rename from server/wal/wal_test.go
rename to server/storage/wal/wal_test.go
index 0501408..d20d561 100644
--- a/server/wal/wal_test.go
+++ b/server/storage/wal/wal_test.go
@@ -31,7 +31,7 @@
 	"go.etcd.io/etcd/client/pkg/v3/fileutil"
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.uber.org/zap/zaptest"
 
 	"go.uber.org/zap"
diff --git a/server/wal/walpb/record.go b/server/storage/wal/walpb/record.go
similarity index 100%
rename from server/wal/walpb/record.go
rename to server/storage/wal/walpb/record.go
diff --git a/server/wal/walpb/record.pb.go b/server/storage/wal/walpb/record.pb.go
similarity index 100%
rename from server/wal/walpb/record.pb.go
rename to server/storage/wal/walpb/record.pb.go
diff --git a/server/wal/walpb/record.proto b/server/storage/wal/walpb/record.proto
similarity index 100%
rename from server/wal/walpb/record.proto
rename to server/storage/wal/walpb/record.proto
diff --git a/server/wal/walpb/record_test.go b/server/storage/wal/walpb/record_test.go
similarity index 100%
rename from server/wal/walpb/record_test.go
rename to server/storage/wal/walpb/record_test.go
diff --git a/server/verify/verify.go b/server/verify/verify.go
index fe34f7a..f1de10b 100644
--- a/server/verify/verify.go
+++ b/server/verify/verify.go
@@ -19,11 +19,11 @@
 	"os"
 
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/datadir"
 	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 	"go.etcd.io/etcd/server/v3/storage/schema"
-	wal2 "go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	wal2 "go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.uber.org/zap"
 )
 
diff --git a/tests/e2e/etcd_corrupt_test.go b/tests/e2e/etcd_corrupt_test.go
index edc95c0..0fd7be3 100644
--- a/tests/e2e/etcd_corrupt_test.go
+++ b/tests/e2e/etcd_corrupt_test.go
@@ -25,7 +25,7 @@
 	bolt "go.etcd.io/bbolt"
 	"go.etcd.io/etcd/api/v3/mvccpb"
 	"go.etcd.io/etcd/client/v3"
-	"go.etcd.io/etcd/server/v3/datadir"
+	"go.etcd.io/etcd/server/v3/storage/datadir"
 )
 
 // TODO: test with embedded etcd in integration package
diff --git a/tests/e2e/utl_migrate_test.go b/tests/e2e/utl_migrate_test.go
new file mode 100644
index 0000000..dee79a0
--- /dev/null
+++ b/tests/e2e/utl_migrate_test.go
@@ -0,0 +1,163 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package e2e
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/coreos/go-semver/semver"
+	"github.com/stretchr/testify/assert"
+	"go.etcd.io/etcd/client/pkg/v3/fileutil"
+	"go.etcd.io/etcd/server/v3/storage/backend"
+	"go.etcd.io/etcd/server/v3/storage/schema"
+)
+
+func TestEtctlutlMigrate(t *testing.T) {
+	lastReleaseBinary := binDir + "/etcd-last-release"
+
+	tcs := []struct {
+		name          string
+		targetVersion string
+		binary        string
+		force         bool
+
+		expectLogsSubString  string
+		expectStorageVersion *semver.Version
+	}{
+		{
+			name:                 "Invalid target version string",
+			targetVersion:        "abc",
+			expectLogsSubString:  `Error: wrong target version format, expected "X.Y", got "abc"`,
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                 "Invalid target version",
+			targetVersion:        "3.a",
+			expectLogsSubString:  `Error: failed to parse target version: strconv.ParseInt: parsing "a": invalid syntax`,
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                 "Target with only major version is invalid",
+			targetVersion:        "3",
+			expectLogsSubString:  `Error: wrong target version format, expected "X.Y", got "3"`,
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                 "Target with patch version is invalid",
+			targetVersion:        "3.6.0",
+			expectLogsSubString:  `Error: wrong target version format, expected "X.Y", got "3.6.0"`,
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                "Migrate v3.5 to v3.5 is no-op",
+			binary:              lastReleaseBinary,
+			targetVersion:       "3.5",
+			expectLogsSubString: "storage version up-to-date\t" + `{"storage-version": "3.5"}`,
+		},
+		{
+			name:                "Upgrade v3.5 to v3.6 should fail until it's implemented",
+			binary:              lastReleaseBinary,
+			targetVersion:       "3.6",
+			expectLogsSubString: "Error: storage version migration is not yet supported",
+		},
+		{
+			name:                 "Migrate v3.6 to v3.6 is no-op",
+			targetVersion:        "3.6",
+			expectLogsSubString:  "storage version up-to-date\t" + `{"storage-version": "3.6"}`,
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                 "Downgrade v3.6 to v3.5 should fail until it's implemented",
+			targetVersion:        "3.5",
+			expectLogsSubString:  "Error: storage version migration is not yet supported",
+			expectStorageVersion: &schema.V3_6,
+		},
+		{
+			name:                "Downgrade v3.6 to v3.5 with force should work",
+			targetVersion:       "3.5",
+			force:               true,
+			expectLogsSubString: "forcefully cleared storage version",
+		},
+		{
+			name:                 "Upgrade v3.6 to v3.7 with force should work",
+			targetVersion:        "3.7",
+			force:                true,
+			expectLogsSubString:  "forcefully set storage version\t" + `{"storage-version": "3.7"}`,
+			expectStorageVersion: &semver.Version{Major: 3, Minor: 7},
+		},
+	}
+	for _, tc := range tcs {
+		t.Run(tc.name, func(t *testing.T) {
+			BeforeTest(t)
+			if tc.binary != "" && !fileutil.Exist(tc.binary) {
+				t.Skipf("%q does not exist", lastReleaseBinary)
+			}
+			dataDirPath := t.TempDir()
+
+			epc, err := newEtcdProcessCluster(t, &etcdProcessClusterConfig{
+				execPath:     tc.binary,
+				dataDirPath:  dataDirPath,
+				clusterSize:  1,
+				initialToken: "new",
+				keepDataDir:  true,
+				// Set low snapshotCount to ensure wal snapshot is done
+				snapshotCount: 1,
+			})
+			if err != nil {
+				t.Fatalf("could not start etcd process cluster (%v)", err)
+			}
+			defer func() {
+				if errC := epc.Close(); errC != nil {
+					t.Fatalf("error closing etcd processes (%v)", errC)
+				}
+			}()
+
+			dialTimeout := 10 * time.Second
+			prefixArgs := []string{ctlBinPath, "--endpoints", strings.Join(epc.EndpointsV3(), ","), "--dial-timeout", dialTimeout.String()}
+
+			t.Log("Write keys to ensure wal snapshot is created and all v3.5 fields are set...")
+			for i := 0; i < 10; i++ {
+				if err = spawnWithExpect(append(prefixArgs, "put", fmt.Sprintf("%d", i), "value"), "OK"); err != nil {
+					t.Fatal(err)
+				}
+			}
+
+			t.Log("Stopping the server...")
+			if err = epc.procs[0].Stop(); err != nil {
+				t.Fatal(err)
+			}
+
+			t.Log("etcdutl migrate...")
+			args := []string{utlBinPath, "migrate", "--data-dir", dataDirPath, "--target-version", tc.targetVersion}
+			if tc.force {
+				args = append(args, "--force")
+			}
+			err = spawnWithExpect(args, tc.expectLogsSubString)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			t.Log("etcdutl migrate...")
+			be := backend.NewDefaultBackend(dataDirPath + "/member/snap/db")
+			defer be.Close()
+
+			ver := schema.ReadStorageVersion(be.ReadTx())
+			assert.Equal(t, tc.expectStorageVersion, ver)
+		})
+	}
+}
diff --git a/tests/e2e/v3_curl_lease_test.go b/tests/e2e/v3_curl_lease_test.go
index ae0d523..80d21e6 100644
--- a/tests/e2e/v3_curl_lease_test.go
+++ b/tests/e2e/v3_curl_lease_test.go
@@ -48,8 +48,6 @@
 	expected string
 }
 
-// TODO remove /kv/lease/timetolive, /kv/lease/revoke, /kv/lease/leases tests in 3.5 release
-
 func testV3CurlLeaseGrant(cx ctlCtx) {
 	leaseID := randomLeaseID()
 
@@ -74,11 +72,6 @@
 			value:    gwLeaseTTLWithKeys(cx, leaseID),
 			expected: `"grantedTTL"`,
 		},
-		{
-			endpoint: "/kv/lease/timetolive",
-			value:    gwLeaseTTLWithKeys(cx, leaseID),
-			expected: `"grantedTTL"`,
-		},
 	}
 	if err := cURLWithExpected(cx, tests); err != nil {
 		cx.t.Fatalf("testV3CurlLeaseGrant: %v", err)
@@ -99,11 +92,6 @@
 			value:    gwLeaseRevoke(cx, leaseID),
 			expected: `"revision":"`,
 		},
-		{
-			endpoint: "/kv/lease/revoke",
-			value:    gwLeaseRevoke(cx, leaseID),
-			expected: `etcdserver: requested lease not found`,
-		},
 	}
 	if err := cURLWithExpected(cx, tests); err != nil {
 		cx.t.Fatalf("testV3CurlLeaseRevoke: %v", err)
@@ -124,11 +112,6 @@
 			value:    "{}",
 			expected: gwLeaseIDExpected(leaseID),
 		},
-		{
-			endpoint: "/kv/lease/leases",
-			value:    "{}",
-			expected: gwLeaseIDExpected(leaseID),
-		},
 	}
 	if err := cURLWithExpected(cx, tests); err != nil {
 		cx.t.Fatalf("testV3CurlLeaseGrant: %v", err)
diff --git a/tests/e2e/v3_curl_test.go b/tests/e2e/v3_curl_test.go
index 7c69711..4a4e828 100644
--- a/tests/e2e/v3_curl_test.go
+++ b/tests/e2e/v3_curl_test.go
@@ -31,8 +31,7 @@
 	"github.com/grpc-ecosystem/grpc-gateway/runtime"
 )
 
-// TODO: remove /v3beta tests in 3.5 release
-var apiPrefix = []string{"/v3", "/v3beta"}
+var apiPrefix = []string{"/v3"}
 
 func TestV3CurlPutGetNoTLS(t *testing.T) {
 	for _, p := range apiPrefix {
diff --git a/tests/go.mod b/tests/go.mod
index 6d6bc4b..b86b5c5 100644
--- a/tests/go.mod
+++ b/tests/go.mod
@@ -15,6 +15,7 @@
 )
 
 require (
+	github.com/coreos/go-semver v0.3.0
 	github.com/dustin/go-humanize v1.0.0
 	github.com/gogo/protobuf v1.3.2
 	github.com/golang/protobuf v1.5.2
diff --git a/tests/go.sum b/tests/go.sum
index c19ecd1..3eb0545 100644
--- a/tests/go.sum
+++ b/tests/go.sum
@@ -77,8 +77,6 @@
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
-github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
 github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -97,6 +95,8 @@
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
diff --git a/tests/integration/cluster.go b/tests/integration/cluster.go
index b54a3e5..cbf8ada 100644
--- a/tests/integration/cluster.go
+++ b/tests/integration/cluster.go
@@ -705,6 +705,7 @@
 
 	m.InitialCorruptCheck = true
 	m.WarningApplyDuration = embed.DefaultWarningApplyDuration
+	m.WarningUnaryRequestDuration = embed.DefaultWarningUnaryRequestDuration
 
 	m.V2Deprecation = config.V2_DEPR_DEFAULT
 
diff --git a/tests/integration/metrics_test.go b/tests/integration/metrics_test.go
index 61276fc..86636ce 100644
--- a/tests/integration/metrics_test.go
+++ b/tests/integration/metrics_test.go
@@ -24,7 +24,7 @@
 
 	pb "go.etcd.io/etcd/api/v3/etcdserverpb"
 	"go.etcd.io/etcd/client/pkg/v3/transport"
-	"go.etcd.io/etcd/server/v3/etcdserver"
+	"go.etcd.io/etcd/server/v3/storage"
 )
 
 // TestMetricDbSizeBoot checks that the db size metric is set on boot.
@@ -175,8 +175,8 @@
 	if err != nil {
 		t.Fatal(err)
 	}
-	if int64(qv) != etcdserver.DefaultQuotaBytes {
-		t.Fatalf("expected %d, got %f", etcdserver.DefaultQuotaBytes, qv)
+	if int64(qv) != storage.DefaultQuotaBytes {
+		t.Fatalf("expected %d, got %f", storage.DefaultQuotaBytes, qv)
 	}
 }
 
diff --git a/tests/integration/utl_wal_version_test.go b/tests/integration/utl_wal_version_test.go
new file mode 100644
index 0000000..1290b76
--- /dev/null
+++ b/tests/integration/utl_wal_version_test.go
@@ -0,0 +1,69 @@
+// Copyright 2021 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package integration
+
+import (
+	"context"
+	"testing"
+	"time"
+
+	"github.com/coreos/go-semver/semver"
+	"github.com/stretchr/testify/assert"
+	"go.uber.org/zap"
+
+	"go.etcd.io/etcd/client/pkg/v3/testutil"
+	clientv3 "go.etcd.io/etcd/client/v3"
+	"go.etcd.io/etcd/server/v3/embed"
+	"go.etcd.io/etcd/server/v3/storage/schema"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
+)
+
+func TestEtcdVersionFromWAL(t *testing.T) {
+	testutil.SkipTestIfShortMode(t,
+		"Wal creation tests are depending on embedded etcServer so are integration-level tests.")
+	cfg := NewEmbedConfig(t, "default")
+	srv, err := embed.StartEtcd(cfg)
+	if err != nil {
+		t.Fatal(err)
+	}
+	select {
+	case <-srv.Server.ReadyNotify():
+	case <-time.After(3 * time.Second):
+		t.Fatalf("failed to start embed.Etcd for test")
+	}
+
+	ccfg := clientv3.Config{Endpoints: []string{cfg.ACUrls[0].String()}}
+	cli, err := NewClient(t, ccfg)
+	if err != nil {
+		srv.Close()
+		t.Fatal(err)
+	}
+	// Get auth status to increase etcd version of proto stored in wal
+	ctx, cancel := context.WithTimeout(context.Background(), testutil.RequestTimeout)
+	cli.AuthStatus(ctx)
+	cancel()
+
+	cli.Close()
+	srv.Close()
+
+	wal, err := wal.Open(zap.NewNop(), cfg.Dir+"/member/wal", walpb.Snapshot{})
+	if err != nil {
+		panic(err)
+	}
+	defer wal.Close()
+	ver := schema.MinimalStorageVersionFromWAL(wal)
+	assert.Equal(t, &semver.Version{Major: 3, Minor: 5}, ver)
+}
diff --git a/tests/manual/Makefile b/tests/manual/Makefile
new file mode 100644
index 0000000..87ee9e8
--- /dev/null
+++ b/tests/manual/Makefile
@@ -0,0 +1,283 @@
+TMP_DOCKERFILE:=$(shell mktemp)
+GO_VERSION ?= 1.16.3
+TMP_DIR_MOUNT_FLAG = --tmpfs=/tmp:exec
+ifdef HOST_TMP_DIR
+	TMP_DIR_MOUNT_FLAG = --mount type=bind,source=$(HOST_TMP_DIR),destination=/tmp
+endif
+
+# Example:
+#   make build-docker-test
+#   make compile-with-docker-test
+#   make build-docker-static-ip-test
+#
+#   gcloud auth configure-docker
+#   make push-docker-static-ip-test
+#
+#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
+#   make pull-docker-static-ip-test
+#
+#   make docker-static-ip-test-certs-run
+#   make docker-static-ip-test-certs-metrics-proxy-run
+
+build-docker-static-ip-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' ./docker-static-ip/Dockerfile > $(TMP_DOCKERFILE)
+	docker build \
+	  --network=host \
+	  --tag gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
+	  --file ./docker-static-ip/Dockerfile \
+	  $(TMP_DOCKERFILE)
+
+push-docker-static-ip-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker push gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION)
+
+pull-docker-static-ip-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker pull gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION)
+
+docker-static-ip-test-certs-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-static-ip/certs,destination=/certs \
+	  gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
+
+docker-static-ip-test-certs-metrics-proxy-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-static-ip/certs-metrics-proxy,destination=/certs-metrics-proxy \
+	  gcr.io/etcd-development/etcd-static-ip-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-metrics-proxy/run.sh && rm -rf m*.etcd"
+
+
+
+# Example:
+#   make build-docker-test
+#   make compile-with-docker-test
+#   make build-docker-dns-test
+#
+#   gcloud auth configure-docker
+#   make push-docker-dns-test
+#
+#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
+#   make pull-docker-dns-test
+#
+#   make docker-dns-test-insecure-run
+#   make docker-dns-test-certs-run
+#   make docker-dns-test-certs-gateway-run
+#   make docker-dns-test-certs-wildcard-run
+#   make docker-dns-test-certs-common-name-auth-run
+#   make docker-dns-test-certs-common-name-multi-run
+#   make docker-dns-test-certs-san-dns-run
+
+build-docker-dns-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' ./docker-dns/Dockerfile > $(TMP_DOCKERFILE)
+	docker build \
+	  --network=host \
+	  --tag gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  --file ./docker-dns/Dockerfile \
+	  $(TMP_DOCKERFILE)
+
+	docker run \
+	  --rm \
+	  --dns 127.0.0.1 \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "/etc/init.d/bind9 start && cat /dev/null >/etc/hosts && dig etcd.local"
+
+push-docker-dns-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker push gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION)
+
+pull-docker-dns-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker pull gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION)
+
+docker-dns-test-insecure-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/insecure,destination=/insecure \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /insecure/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs,destination=/certs \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-gateway-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-gateway,destination=/certs-gateway \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-gateway/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-wildcard-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-wildcard,destination=/certs-wildcard \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-wildcard/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-common-name-auth-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-common-name-auth,destination=/certs-common-name-auth \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-common-name-auth/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-common-name-multi-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-common-name-multi,destination=/certs-common-name-multi \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-common-name-multi/run.sh && rm -rf m*.etcd"
+
+docker-dns-test-certs-san-dns-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns/certs-san-dns,destination=/certs-san-dns \
+	  gcr.io/etcd-development/etcd-dns-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-san-dns/run.sh && rm -rf m*.etcd"
+
+
+# Example:
+#   make build-docker-test
+#   make compile-with-docker-test
+#   make build-docker-dns-srv-test
+#   gcloud auth configure-docker
+#   make push-docker-dns-srv-test
+#   gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
+#   make pull-docker-dns-srv-test
+#   make docker-dns-srv-test-certs-run
+#   make docker-dns-srv-test-certs-gateway-run
+#   make docker-dns-srv-test-certs-wildcard-run
+
+build-docker-dns-srv-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	@sed 's|REPLACE_ME_GO_VERSION|$(GO_VERSION)|g' > $(TMP_DOCKERFILE)
+	docker build \
+	  --network=host \
+	  --tag gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
+	  --file ./docker-dns-srv/Dockerfile \
+	  $(TMP_DOCKERFILE)
+
+	docker run \
+	  --rm \
+	  --dns 127.0.0.1 \
+	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
+	  /bin/bash -c "/etc/init.d/bind9 start && cat /dev/null >/etc/hosts && dig +noall +answer SRV _etcd-client-ssl._tcp.etcd.local && dig +noall +answer SRV _etcd-server-ssl._tcp.etcd.local && dig +noall +answer m1.etcd.local m2.etcd.local m3.etcd.local"
+
+push-docker-dns-srv-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker push gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION)
+
+pull-docker-dns-srv-test:
+	$(info GO_VERSION: $(GO_VERSION))
+	docker pull gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION)
+
+docker-dns-srv-test-certs-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs,destination=/certs \
+	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs/run.sh && rm -rf m*.etcd"
+
+docker-dns-srv-test-certs-gateway-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs-gateway,destination=/certs-gateway \
+	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-gateway/run.sh && rm -rf m*.etcd"
+
+docker-dns-srv-test-certs-wildcard-run:
+	$(info GO_VERSION: $(GO_VERSION))
+	$(info HOST_TMP_DIR: $(HOST_TMP_DIR))
+	$(info TMP_DIR_MOUNT_FLAG: $(TMP_DIR_MOUNT_FLAG))
+	docker run \
+	  --rm \
+	  --tty \
+	  --dns 127.0.0.1 \
+	  $(TMP_DIR_MOUNT_FLAG) \
+	  --mount type=bind,source=`pwd`/bin,destination=/etcd \
+	  --mount type=bind,source=`pwd`/tests/docker-dns-srv/certs-wildcard,destination=/certs-wildcard \
+	  gcr.io/etcd-development/etcd-dns-srv-test:go$(GO_VERSION) \
+	  /bin/bash -c "cd /etcd && /certs-wildcard/run.sh && rm -rf m*.etcd"
diff --git a/tests/docker-dns-srv/Dockerfile b/tests/manual/docker-dns-srv/Dockerfile
similarity index 100%
rename from tests/docker-dns-srv/Dockerfile
rename to tests/manual/docker-dns-srv/Dockerfile
diff --git a/tests/docker-dns-srv/certs-gateway/Procfile b/tests/manual/docker-dns-srv/certs-gateway/Procfile
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/Procfile
rename to tests/manual/docker-dns-srv/certs-gateway/Procfile
diff --git a/tests/docker-dns-srv/certs-gateway/ca-csr.json b/tests/manual/docker-dns-srv/certs-gateway/ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/ca-csr.json
rename to tests/manual/docker-dns-srv/certs-gateway/ca-csr.json
diff --git a/tests/docker-dns-srv/certs-gateway/ca.crt b/tests/manual/docker-dns-srv/certs-gateway/ca.crt
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/ca.crt
rename to tests/manual/docker-dns-srv/certs-gateway/ca.crt
diff --git a/tests/docker-dns-srv/certs-gateway/gencert.json b/tests/manual/docker-dns-srv/certs-gateway/gencert.json
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/gencert.json
rename to tests/manual/docker-dns-srv/certs-gateway/gencert.json
diff --git a/tests/docker-dns-srv/certs-gateway/gencerts.sh b/tests/manual/docker-dns-srv/certs-gateway/gencerts.sh
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/gencerts.sh
rename to tests/manual/docker-dns-srv/certs-gateway/gencerts.sh
diff --git a/tests/docker-dns-srv/certs-gateway/run.sh b/tests/manual/docker-dns-srv/certs-gateway/run.sh
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/run.sh
rename to tests/manual/docker-dns-srv/certs-gateway/run.sh
diff --git a/tests/docker-dns-srv/certs-gateway/server-ca-csr.json b/tests/manual/docker-dns-srv/certs-gateway/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/server-ca-csr.json
rename to tests/manual/docker-dns-srv/certs-gateway/server-ca-csr.json
diff --git a/tests/docker-dns-srv/certs-gateway/server.crt b/tests/manual/docker-dns-srv/certs-gateway/server.crt
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/server.crt
rename to tests/manual/docker-dns-srv/certs-gateway/server.crt
diff --git a/tests/docker-dns-srv/certs-gateway/server.key.insecure b/tests/manual/docker-dns-srv/certs-gateway/server.key.insecure
similarity index 100%
rename from tests/docker-dns-srv/certs-gateway/server.key.insecure
rename to tests/manual/docker-dns-srv/certs-gateway/server.key.insecure
diff --git a/tests/docker-dns-srv/certs-wildcard/Procfile b/tests/manual/docker-dns-srv/certs-wildcard/Procfile
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/Procfile
rename to tests/manual/docker-dns-srv/certs-wildcard/Procfile
diff --git a/tests/docker-dns-srv/certs-wildcard/ca-csr.json b/tests/manual/docker-dns-srv/certs-wildcard/ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/ca-csr.json
rename to tests/manual/docker-dns-srv/certs-wildcard/ca-csr.json
diff --git a/tests/docker-dns-srv/certs-wildcard/ca.crt b/tests/manual/docker-dns-srv/certs-wildcard/ca.crt
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/ca.crt
rename to tests/manual/docker-dns-srv/certs-wildcard/ca.crt
diff --git a/tests/docker-dns-srv/certs-wildcard/gencert.json b/tests/manual/docker-dns-srv/certs-wildcard/gencert.json
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/gencert.json
rename to tests/manual/docker-dns-srv/certs-wildcard/gencert.json
diff --git a/tests/docker-dns-srv/certs-wildcard/gencerts.sh b/tests/manual/docker-dns-srv/certs-wildcard/gencerts.sh
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/gencerts.sh
rename to tests/manual/docker-dns-srv/certs-wildcard/gencerts.sh
diff --git a/tests/docker-dns-srv/certs-wildcard/run.sh b/tests/manual/docker-dns-srv/certs-wildcard/run.sh
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/run.sh
rename to tests/manual/docker-dns-srv/certs-wildcard/run.sh
diff --git a/tests/docker-dns-srv/certs-wildcard/server-ca-csr.json b/tests/manual/docker-dns-srv/certs-wildcard/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/server-ca-csr.json
rename to tests/manual/docker-dns-srv/certs-wildcard/server-ca-csr.json
diff --git a/tests/docker-dns-srv/certs-wildcard/server.crt b/tests/manual/docker-dns-srv/certs-wildcard/server.crt
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/server.crt
rename to tests/manual/docker-dns-srv/certs-wildcard/server.crt
diff --git a/tests/docker-dns-srv/certs-wildcard/server.key.insecure b/tests/manual/docker-dns-srv/certs-wildcard/server.key.insecure
similarity index 100%
rename from tests/docker-dns-srv/certs-wildcard/server.key.insecure
rename to tests/manual/docker-dns-srv/certs-wildcard/server.key.insecure
diff --git a/tests/docker-dns-srv/certs/Procfile b/tests/manual/docker-dns-srv/certs/Procfile
similarity index 100%
rename from tests/docker-dns-srv/certs/Procfile
rename to tests/manual/docker-dns-srv/certs/Procfile
diff --git a/tests/docker-dns-srv/certs/ca-csr.json b/tests/manual/docker-dns-srv/certs/ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs/ca-csr.json
rename to tests/manual/docker-dns-srv/certs/ca-csr.json
diff --git a/tests/docker-dns-srv/certs/ca.crt b/tests/manual/docker-dns-srv/certs/ca.crt
similarity index 100%
rename from tests/docker-dns-srv/certs/ca.crt
rename to tests/manual/docker-dns-srv/certs/ca.crt
diff --git a/tests/docker-dns-srv/certs/gencert.json b/tests/manual/docker-dns-srv/certs/gencert.json
similarity index 100%
rename from tests/docker-dns-srv/certs/gencert.json
rename to tests/manual/docker-dns-srv/certs/gencert.json
diff --git a/tests/docker-dns-srv/certs/gencerts.sh b/tests/manual/docker-dns-srv/certs/gencerts.sh
similarity index 100%
rename from tests/docker-dns-srv/certs/gencerts.sh
rename to tests/manual/docker-dns-srv/certs/gencerts.sh
diff --git a/tests/docker-dns-srv/certs/run.sh b/tests/manual/docker-dns-srv/certs/run.sh
similarity index 100%
rename from tests/docker-dns-srv/certs/run.sh
rename to tests/manual/docker-dns-srv/certs/run.sh
diff --git a/tests/docker-dns-srv/certs/server-ca-csr.json b/tests/manual/docker-dns-srv/certs/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns-srv/certs/server-ca-csr.json
rename to tests/manual/docker-dns-srv/certs/server-ca-csr.json
diff --git a/tests/docker-dns-srv/certs/server.crt b/tests/manual/docker-dns-srv/certs/server.crt
similarity index 100%
rename from tests/docker-dns-srv/certs/server.crt
rename to tests/manual/docker-dns-srv/certs/server.crt
diff --git a/tests/docker-dns-srv/certs/server.key.insecure b/tests/manual/docker-dns-srv/certs/server.key.insecure
similarity index 100%
rename from tests/docker-dns-srv/certs/server.key.insecure
rename to tests/manual/docker-dns-srv/certs/server.key.insecure
diff --git a/tests/docker-dns-srv/etcd.zone b/tests/manual/docker-dns-srv/etcd.zone
similarity index 100%
rename from tests/docker-dns-srv/etcd.zone
rename to tests/manual/docker-dns-srv/etcd.zone
diff --git a/tests/docker-dns-srv/named.conf b/tests/manual/docker-dns-srv/named.conf
similarity index 100%
rename from tests/docker-dns-srv/named.conf
rename to tests/manual/docker-dns-srv/named.conf
diff --git a/tests/docker-dns-srv/rdns.zone b/tests/manual/docker-dns-srv/rdns.zone
similarity index 100%
rename from tests/docker-dns-srv/rdns.zone
rename to tests/manual/docker-dns-srv/rdns.zone
diff --git a/tests/docker-dns-srv/resolv.conf b/tests/manual/docker-dns-srv/resolv.conf
similarity index 100%
rename from tests/docker-dns-srv/resolv.conf
rename to tests/manual/docker-dns-srv/resolv.conf
diff --git a/tests/docker-dns/Dockerfile b/tests/manual/docker-dns/Dockerfile
similarity index 100%
rename from tests/docker-dns/Dockerfile
rename to tests/manual/docker-dns/Dockerfile
diff --git a/tests/docker-dns/certs-common-name-auth/Procfile b/tests/manual/docker-dns/certs-common-name-auth/Procfile
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/Procfile
rename to tests/manual/docker-dns/certs-common-name-auth/Procfile
diff --git a/tests/docker-dns/certs-common-name-auth/ca-csr.json b/tests/manual/docker-dns/certs-common-name-auth/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/ca-csr.json
rename to tests/manual/docker-dns/certs-common-name-auth/ca-csr.json
diff --git a/tests/docker-dns/certs-common-name-auth/ca.crt b/tests/manual/docker-dns/certs-common-name-auth/ca.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/ca.crt
rename to tests/manual/docker-dns/certs-common-name-auth/ca.crt
diff --git a/tests/docker-dns/certs-common-name-auth/gencert.json b/tests/manual/docker-dns/certs-common-name-auth/gencert.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/gencert.json
rename to tests/manual/docker-dns/certs-common-name-auth/gencert.json
diff --git a/tests/docker-dns/certs-common-name-auth/gencerts.sh b/tests/manual/docker-dns/certs-common-name-auth/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/gencerts.sh
rename to tests/manual/docker-dns/certs-common-name-auth/gencerts.sh
diff --git a/tests/docker-dns/certs-common-name-auth/run.sh b/tests/manual/docker-dns/certs-common-name-auth/run.sh
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/run.sh
rename to tests/manual/docker-dns/certs-common-name-auth/run.sh
diff --git a/tests/docker-dns/certs-common-name-auth/server-ca-csr.json b/tests/manual/docker-dns/certs-common-name-auth/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/server-ca-csr.json
rename to tests/manual/docker-dns/certs-common-name-auth/server-ca-csr.json
diff --git a/tests/docker-dns/certs-common-name-auth/server.crt b/tests/manual/docker-dns/certs-common-name-auth/server.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/server.crt
rename to tests/manual/docker-dns/certs-common-name-auth/server.crt
diff --git a/tests/docker-dns/certs-common-name-auth/server.key.insecure b/tests/manual/docker-dns/certs-common-name-auth/server.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-common-name-auth/server.key.insecure
rename to tests/manual/docker-dns/certs-common-name-auth/server.key.insecure
diff --git a/tests/docker-dns/certs-common-name-multi/Procfile b/tests/manual/docker-dns/certs-common-name-multi/Procfile
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/Procfile
rename to tests/manual/docker-dns/certs-common-name-multi/Procfile
diff --git a/tests/docker-dns/certs-common-name-multi/ca-csr.json b/tests/manual/docker-dns/certs-common-name-multi/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/ca-csr.json
rename to tests/manual/docker-dns/certs-common-name-multi/ca-csr.json
diff --git a/tests/docker-dns/certs-common-name-multi/ca.crt b/tests/manual/docker-dns/certs-common-name-multi/ca.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/ca.crt
rename to tests/manual/docker-dns/certs-common-name-multi/ca.crt
diff --git a/tests/docker-dns/certs-common-name-multi/gencert.json b/tests/manual/docker-dns/certs-common-name-multi/gencert.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/gencert.json
rename to tests/manual/docker-dns/certs-common-name-multi/gencert.json
diff --git a/tests/docker-dns/certs-common-name-multi/gencerts.sh b/tests/manual/docker-dns/certs-common-name-multi/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/gencerts.sh
rename to tests/manual/docker-dns/certs-common-name-multi/gencerts.sh
diff --git a/tests/docker-dns/certs-common-name-multi/run.sh b/tests/manual/docker-dns/certs-common-name-multi/run.sh
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/run.sh
rename to tests/manual/docker-dns/certs-common-name-multi/run.sh
diff --git a/tests/docker-dns/certs-common-name-multi/server-1.crt b/tests/manual/docker-dns/certs-common-name-multi/server-1.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-1.crt
rename to tests/manual/docker-dns/certs-common-name-multi/server-1.crt
diff --git a/tests/docker-dns/certs-common-name-multi/server-1.key.insecure b/tests/manual/docker-dns/certs-common-name-multi/server-1.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-1.key.insecure
rename to tests/manual/docker-dns/certs-common-name-multi/server-1.key.insecure
diff --git a/tests/docker-dns/certs-common-name-multi/server-2.crt b/tests/manual/docker-dns/certs-common-name-multi/server-2.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-2.crt
rename to tests/manual/docker-dns/certs-common-name-multi/server-2.crt
diff --git a/tests/docker-dns/certs-common-name-multi/server-2.key.insecure b/tests/manual/docker-dns/certs-common-name-multi/server-2.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-2.key.insecure
rename to tests/manual/docker-dns/certs-common-name-multi/server-2.key.insecure
diff --git a/tests/docker-dns/certs-common-name-multi/server-3.crt b/tests/manual/docker-dns/certs-common-name-multi/server-3.crt
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-3.crt
rename to tests/manual/docker-dns/certs-common-name-multi/server-3.crt
diff --git a/tests/docker-dns/certs-common-name-multi/server-3.key.insecure b/tests/manual/docker-dns/certs-common-name-multi/server-3.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-3.key.insecure
rename to tests/manual/docker-dns/certs-common-name-multi/server-3.key.insecure
diff --git a/tests/docker-dns/certs-common-name-multi/server-ca-csr-1.json b/tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-1.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-ca-csr-1.json
rename to tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-1.json
diff --git a/tests/docker-dns/certs-common-name-multi/server-ca-csr-2.json b/tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-2.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-ca-csr-2.json
rename to tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-2.json
diff --git a/tests/docker-dns/certs-common-name-multi/server-ca-csr-3.json b/tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-3.json
similarity index 100%
rename from tests/docker-dns/certs-common-name-multi/server-ca-csr-3.json
rename to tests/manual/docker-dns/certs-common-name-multi/server-ca-csr-3.json
diff --git a/tests/docker-dns/certs-gateway/Procfile b/tests/manual/docker-dns/certs-gateway/Procfile
similarity index 100%
rename from tests/docker-dns/certs-gateway/Procfile
rename to tests/manual/docker-dns/certs-gateway/Procfile
diff --git a/tests/docker-dns/certs-gateway/ca-csr.json b/tests/manual/docker-dns/certs-gateway/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-gateway/ca-csr.json
rename to tests/manual/docker-dns/certs-gateway/ca-csr.json
diff --git a/tests/docker-dns/certs-gateway/ca.crt b/tests/manual/docker-dns/certs-gateway/ca.crt
similarity index 100%
rename from tests/docker-dns/certs-gateway/ca.crt
rename to tests/manual/docker-dns/certs-gateway/ca.crt
diff --git a/tests/docker-dns/certs-gateway/gencert.json b/tests/manual/docker-dns/certs-gateway/gencert.json
similarity index 100%
rename from tests/docker-dns/certs-gateway/gencert.json
rename to tests/manual/docker-dns/certs-gateway/gencert.json
diff --git a/tests/docker-dns/certs-gateway/gencerts.sh b/tests/manual/docker-dns/certs-gateway/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs-gateway/gencerts.sh
rename to tests/manual/docker-dns/certs-gateway/gencerts.sh
diff --git a/tests/docker-dns/certs-gateway/run.sh b/tests/manual/docker-dns/certs-gateway/run.sh
similarity index 100%
rename from tests/docker-dns/certs-gateway/run.sh
rename to tests/manual/docker-dns/certs-gateway/run.sh
diff --git a/tests/docker-dns/certs-gateway/server-ca-csr.json b/tests/manual/docker-dns/certs-gateway/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-gateway/server-ca-csr.json
rename to tests/manual/docker-dns/certs-gateway/server-ca-csr.json
diff --git a/tests/docker-dns/certs-gateway/server.crt b/tests/manual/docker-dns/certs-gateway/server.crt
similarity index 100%
rename from tests/docker-dns/certs-gateway/server.crt
rename to tests/manual/docker-dns/certs-gateway/server.crt
diff --git a/tests/docker-dns/certs-gateway/server.key.insecure b/tests/manual/docker-dns/certs-gateway/server.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-gateway/server.key.insecure
rename to tests/manual/docker-dns/certs-gateway/server.key.insecure
diff --git a/tests/docker-dns/certs-san-dns/Procfile b/tests/manual/docker-dns/certs-san-dns/Procfile
similarity index 100%
rename from tests/docker-dns/certs-san-dns/Procfile
rename to tests/manual/docker-dns/certs-san-dns/Procfile
diff --git a/tests/docker-dns/certs-san-dns/ca-csr.json b/tests/manual/docker-dns/certs-san-dns/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-san-dns/ca-csr.json
rename to tests/manual/docker-dns/certs-san-dns/ca-csr.json
diff --git a/tests/docker-dns/certs-san-dns/ca.crt b/tests/manual/docker-dns/certs-san-dns/ca.crt
similarity index 100%
rename from tests/docker-dns/certs-san-dns/ca.crt
rename to tests/manual/docker-dns/certs-san-dns/ca.crt
diff --git a/tests/docker-dns/certs-san-dns/gencert.json b/tests/manual/docker-dns/certs-san-dns/gencert.json
similarity index 100%
rename from tests/docker-dns/certs-san-dns/gencert.json
rename to tests/manual/docker-dns/certs-san-dns/gencert.json
diff --git a/tests/docker-dns/certs-san-dns/gencerts.sh b/tests/manual/docker-dns/certs-san-dns/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs-san-dns/gencerts.sh
rename to tests/manual/docker-dns/certs-san-dns/gencerts.sh
diff --git a/tests/docker-dns/certs-san-dns/run.sh b/tests/manual/docker-dns/certs-san-dns/run.sh
similarity index 100%
rename from tests/docker-dns/certs-san-dns/run.sh
rename to tests/manual/docker-dns/certs-san-dns/run.sh
diff --git a/tests/docker-dns/certs-san-dns/server-1.crt b/tests/manual/docker-dns/certs-san-dns/server-1.crt
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-1.crt
rename to tests/manual/docker-dns/certs-san-dns/server-1.crt
diff --git a/tests/docker-dns/certs-san-dns/server-1.key.insecure b/tests/manual/docker-dns/certs-san-dns/server-1.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-1.key.insecure
rename to tests/manual/docker-dns/certs-san-dns/server-1.key.insecure
diff --git a/tests/docker-dns/certs-san-dns/server-2.crt b/tests/manual/docker-dns/certs-san-dns/server-2.crt
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-2.crt
rename to tests/manual/docker-dns/certs-san-dns/server-2.crt
diff --git a/tests/docker-dns/certs-san-dns/server-2.key.insecure b/tests/manual/docker-dns/certs-san-dns/server-2.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-2.key.insecure
rename to tests/manual/docker-dns/certs-san-dns/server-2.key.insecure
diff --git a/tests/docker-dns/certs-san-dns/server-3.crt b/tests/manual/docker-dns/certs-san-dns/server-3.crt
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-3.crt
rename to tests/manual/docker-dns/certs-san-dns/server-3.crt
diff --git a/tests/docker-dns/certs-san-dns/server-3.key.insecure b/tests/manual/docker-dns/certs-san-dns/server-3.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-3.key.insecure
rename to tests/manual/docker-dns/certs-san-dns/server-3.key.insecure
diff --git a/tests/docker-dns/certs-san-dns/server-ca-csr-1.json b/tests/manual/docker-dns/certs-san-dns/server-ca-csr-1.json
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-ca-csr-1.json
rename to tests/manual/docker-dns/certs-san-dns/server-ca-csr-1.json
diff --git a/tests/docker-dns/certs-san-dns/server-ca-csr-2.json b/tests/manual/docker-dns/certs-san-dns/server-ca-csr-2.json
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-ca-csr-2.json
rename to tests/manual/docker-dns/certs-san-dns/server-ca-csr-2.json
diff --git a/tests/docker-dns/certs-san-dns/server-ca-csr-3.json b/tests/manual/docker-dns/certs-san-dns/server-ca-csr-3.json
similarity index 100%
rename from tests/docker-dns/certs-san-dns/server-ca-csr-3.json
rename to tests/manual/docker-dns/certs-san-dns/server-ca-csr-3.json
diff --git a/tests/docker-dns/certs-wildcard/Procfile b/tests/manual/docker-dns/certs-wildcard/Procfile
similarity index 100%
rename from tests/docker-dns/certs-wildcard/Procfile
rename to tests/manual/docker-dns/certs-wildcard/Procfile
diff --git a/tests/docker-dns/certs-wildcard/ca-csr.json b/tests/manual/docker-dns/certs-wildcard/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-wildcard/ca-csr.json
rename to tests/manual/docker-dns/certs-wildcard/ca-csr.json
diff --git a/tests/docker-dns/certs-wildcard/ca.crt b/tests/manual/docker-dns/certs-wildcard/ca.crt
similarity index 100%
rename from tests/docker-dns/certs-wildcard/ca.crt
rename to tests/manual/docker-dns/certs-wildcard/ca.crt
diff --git a/tests/docker-dns/certs-wildcard/gencert.json b/tests/manual/docker-dns/certs-wildcard/gencert.json
similarity index 100%
rename from tests/docker-dns/certs-wildcard/gencert.json
rename to tests/manual/docker-dns/certs-wildcard/gencert.json
diff --git a/tests/docker-dns/certs-wildcard/gencerts.sh b/tests/manual/docker-dns/certs-wildcard/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs-wildcard/gencerts.sh
rename to tests/manual/docker-dns/certs-wildcard/gencerts.sh
diff --git a/tests/docker-dns/certs-wildcard/run.sh b/tests/manual/docker-dns/certs-wildcard/run.sh
similarity index 100%
rename from tests/docker-dns/certs-wildcard/run.sh
rename to tests/manual/docker-dns/certs-wildcard/run.sh
diff --git a/tests/docker-dns/certs-wildcard/server-ca-csr.json b/tests/manual/docker-dns/certs-wildcard/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs-wildcard/server-ca-csr.json
rename to tests/manual/docker-dns/certs-wildcard/server-ca-csr.json
diff --git a/tests/docker-dns/certs-wildcard/server.crt b/tests/manual/docker-dns/certs-wildcard/server.crt
similarity index 100%
rename from tests/docker-dns/certs-wildcard/server.crt
rename to tests/manual/docker-dns/certs-wildcard/server.crt
diff --git a/tests/docker-dns/certs-wildcard/server.key.insecure b/tests/manual/docker-dns/certs-wildcard/server.key.insecure
similarity index 100%
rename from tests/docker-dns/certs-wildcard/server.key.insecure
rename to tests/manual/docker-dns/certs-wildcard/server.key.insecure
diff --git a/tests/docker-dns/certs/Procfile b/tests/manual/docker-dns/certs/Procfile
similarity index 100%
rename from tests/docker-dns/certs/Procfile
rename to tests/manual/docker-dns/certs/Procfile
diff --git a/tests/docker-dns/certs/ca-csr.json b/tests/manual/docker-dns/certs/ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs/ca-csr.json
rename to tests/manual/docker-dns/certs/ca-csr.json
diff --git a/tests/docker-dns/certs/ca.crt b/tests/manual/docker-dns/certs/ca.crt
similarity index 100%
rename from tests/docker-dns/certs/ca.crt
rename to tests/manual/docker-dns/certs/ca.crt
diff --git a/tests/docker-dns/certs/gencert.json b/tests/manual/docker-dns/certs/gencert.json
similarity index 100%
rename from tests/docker-dns/certs/gencert.json
rename to tests/manual/docker-dns/certs/gencert.json
diff --git a/tests/docker-dns/certs/gencerts.sh b/tests/manual/docker-dns/certs/gencerts.sh
similarity index 100%
rename from tests/docker-dns/certs/gencerts.sh
rename to tests/manual/docker-dns/certs/gencerts.sh
diff --git a/tests/docker-dns/certs/run.sh b/tests/manual/docker-dns/certs/run.sh
similarity index 100%
rename from tests/docker-dns/certs/run.sh
rename to tests/manual/docker-dns/certs/run.sh
diff --git a/tests/docker-dns/certs/server-ca-csr.json b/tests/manual/docker-dns/certs/server-ca-csr.json
similarity index 100%
rename from tests/docker-dns/certs/server-ca-csr.json
rename to tests/manual/docker-dns/certs/server-ca-csr.json
diff --git a/tests/docker-dns/certs/server.crt b/tests/manual/docker-dns/certs/server.crt
similarity index 100%
rename from tests/docker-dns/certs/server.crt
rename to tests/manual/docker-dns/certs/server.crt
diff --git a/tests/docker-dns/certs/server.key.insecure b/tests/manual/docker-dns/certs/server.key.insecure
similarity index 100%
rename from tests/docker-dns/certs/server.key.insecure
rename to tests/manual/docker-dns/certs/server.key.insecure
diff --git a/tests/docker-dns/etcd.zone b/tests/manual/docker-dns/etcd.zone
similarity index 100%
rename from tests/docker-dns/etcd.zone
rename to tests/manual/docker-dns/etcd.zone
diff --git a/tests/docker-dns/insecure/Procfile b/tests/manual/docker-dns/insecure/Procfile
similarity index 100%
rename from tests/docker-dns/insecure/Procfile
rename to tests/manual/docker-dns/insecure/Procfile
diff --git a/tests/docker-dns/insecure/run.sh b/tests/manual/docker-dns/insecure/run.sh
similarity index 100%
rename from tests/docker-dns/insecure/run.sh
rename to tests/manual/docker-dns/insecure/run.sh
diff --git a/tests/docker-dns/named.conf b/tests/manual/docker-dns/named.conf
similarity index 100%
rename from tests/docker-dns/named.conf
rename to tests/manual/docker-dns/named.conf
diff --git a/tests/docker-dns/rdns.zone b/tests/manual/docker-dns/rdns.zone
similarity index 100%
rename from tests/docker-dns/rdns.zone
rename to tests/manual/docker-dns/rdns.zone
diff --git a/tests/docker-dns/resolv.conf b/tests/manual/docker-dns/resolv.conf
similarity index 100%
rename from tests/docker-dns/resolv.conf
rename to tests/manual/docker-dns/resolv.conf
diff --git a/tests/docker-static-ip/Dockerfile b/tests/manual/docker-static-ip/Dockerfile
similarity index 100%
rename from tests/docker-static-ip/Dockerfile
rename to tests/manual/docker-static-ip/Dockerfile
diff --git a/tests/docker-static-ip/certs-metrics-proxy/Procfile b/tests/manual/docker-static-ip/certs-metrics-proxy/Procfile
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/Procfile
rename to tests/manual/docker-static-ip/certs-metrics-proxy/Procfile
diff --git a/tests/docker-static-ip/certs-metrics-proxy/ca-csr.json b/tests/manual/docker-static-ip/certs-metrics-proxy/ca-csr.json
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/ca-csr.json
rename to tests/manual/docker-static-ip/certs-metrics-proxy/ca-csr.json
diff --git a/tests/docker-static-ip/certs-metrics-proxy/ca.crt b/tests/manual/docker-static-ip/certs-metrics-proxy/ca.crt
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/ca.crt
rename to tests/manual/docker-static-ip/certs-metrics-proxy/ca.crt
diff --git a/tests/docker-static-ip/certs-metrics-proxy/gencert.json b/tests/manual/docker-static-ip/certs-metrics-proxy/gencert.json
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/gencert.json
rename to tests/manual/docker-static-ip/certs-metrics-proxy/gencert.json
diff --git a/tests/docker-static-ip/certs-metrics-proxy/gencerts.sh b/tests/manual/docker-static-ip/certs-metrics-proxy/gencerts.sh
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/gencerts.sh
rename to tests/manual/docker-static-ip/certs-metrics-proxy/gencerts.sh
diff --git a/tests/docker-static-ip/certs-metrics-proxy/run.sh b/tests/manual/docker-static-ip/certs-metrics-proxy/run.sh
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/run.sh
rename to tests/manual/docker-static-ip/certs-metrics-proxy/run.sh
diff --git a/tests/docker-static-ip/certs-metrics-proxy/server-ca-csr.json b/tests/manual/docker-static-ip/certs-metrics-proxy/server-ca-csr.json
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/server-ca-csr.json
rename to tests/manual/docker-static-ip/certs-metrics-proxy/server-ca-csr.json
diff --git a/tests/docker-static-ip/certs-metrics-proxy/server.crt b/tests/manual/docker-static-ip/certs-metrics-proxy/server.crt
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/server.crt
rename to tests/manual/docker-static-ip/certs-metrics-proxy/server.crt
diff --git a/tests/docker-static-ip/certs-metrics-proxy/server.key.insecure b/tests/manual/docker-static-ip/certs-metrics-proxy/server.key.insecure
similarity index 100%
rename from tests/docker-static-ip/certs-metrics-proxy/server.key.insecure
rename to tests/manual/docker-static-ip/certs-metrics-proxy/server.key.insecure
diff --git a/tests/docker-static-ip/certs/Procfile b/tests/manual/docker-static-ip/certs/Procfile
similarity index 100%
rename from tests/docker-static-ip/certs/Procfile
rename to tests/manual/docker-static-ip/certs/Procfile
diff --git a/tests/docker-static-ip/certs/ca-csr.json b/tests/manual/docker-static-ip/certs/ca-csr.json
similarity index 100%
rename from tests/docker-static-ip/certs/ca-csr.json
rename to tests/manual/docker-static-ip/certs/ca-csr.json
diff --git a/tests/docker-static-ip/certs/ca.crt b/tests/manual/docker-static-ip/certs/ca.crt
similarity index 100%
rename from tests/docker-static-ip/certs/ca.crt
rename to tests/manual/docker-static-ip/certs/ca.crt
diff --git a/tests/docker-static-ip/certs/gencert.json b/tests/manual/docker-static-ip/certs/gencert.json
similarity index 100%
rename from tests/docker-static-ip/certs/gencert.json
rename to tests/manual/docker-static-ip/certs/gencert.json
diff --git a/tests/docker-static-ip/certs/gencerts.sh b/tests/manual/docker-static-ip/certs/gencerts.sh
similarity index 100%
rename from tests/docker-static-ip/certs/gencerts.sh
rename to tests/manual/docker-static-ip/certs/gencerts.sh
diff --git a/tests/docker-static-ip/certs/run.sh b/tests/manual/docker-static-ip/certs/run.sh
similarity index 100%
rename from tests/docker-static-ip/certs/run.sh
rename to tests/manual/docker-static-ip/certs/run.sh
diff --git a/tests/docker-static-ip/certs/server-ca-csr.json b/tests/manual/docker-static-ip/certs/server-ca-csr.json
similarity index 100%
rename from tests/docker-static-ip/certs/server-ca-csr.json
rename to tests/manual/docker-static-ip/certs/server-ca-csr.json
diff --git a/tests/docker-static-ip/certs/server.crt b/tests/manual/docker-static-ip/certs/server.crt
similarity index 100%
rename from tests/docker-static-ip/certs/server.crt
rename to tests/manual/docker-static-ip/certs/server.crt
diff --git a/tests/docker-static-ip/certs/server.key.insecure b/tests/manual/docker-static-ip/certs/server.key.insecure
similarity index 100%
rename from tests/docker-static-ip/certs/server.key.insecure
rename to tests/manual/docker-static-ip/certs/server.key.insecure
diff --git a/tools/benchmark/cmd/put.go b/tools/benchmark/cmd/put.go
index a83d570..366bf1f 100644
--- a/tools/benchmark/cmd/put.go
+++ b/tools/benchmark/cmd/put.go
@@ -171,7 +171,6 @@
 	host := eps[0]
 
 	st := time.Now()
-	clients[0].HashKV(context.Background(), eps[0], 0)
 	rh, eh := clients[0].HashKV(context.Background(), host, 0)
 	if eh != nil {
 		fmt.Fprintf(os.Stderr, "Failed to get the hashkv of endpoint %s (%v)\n", host, eh)
diff --git a/tools/etcd-dump-logs/etcd-dump-log_test.go b/tools/etcd-dump-logs/etcd-dump-log_test.go
index 372f759..e78e896 100644
--- a/tools/etcd-dump-logs/etcd-dump-log_test.go
+++ b/tools/etcd-dump-logs/etcd-dump-log_test.go
@@ -29,7 +29,7 @@
 	"go.etcd.io/etcd/client/pkg/v3/fileutil"
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
-	"go.etcd.io/etcd/server/v3/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal"
 	"go.uber.org/zap"
 )
 
diff --git a/tools/etcd-dump-logs/main.go b/tools/etcd-dump-logs/main.go
index b563563..15c76a4 100644
--- a/tools/etcd-dump-logs/main.go
+++ b/tools/etcd-dump-logs/main.go
@@ -34,8 +34,8 @@
 	"go.etcd.io/etcd/pkg/v3/pbutil"
 	"go.etcd.io/etcd/raft/v3/raftpb"
 	"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
-	"go.etcd.io/etcd/server/v3/wal"
-	"go.etcd.io/etcd/server/v3/wal/walpb"
+	"go.etcd.io/etcd/server/v3/storage/wal"
+	"go.etcd.io/etcd/server/v3/storage/wal/walpb"
 	"go.uber.org/zap"
 )
 
diff --git a/tools/mod/go.mod b/tools/mod/go.mod
index c67cd76..3ce5f03 100644
--- a/tools/mod/go.mod
+++ b/tools/mod/go.mod
@@ -10,7 +10,7 @@
 	github.com/go-openapi/loads v0.19.5 // indirect
 	github.com/go-openapi/spec v0.19.9 // indirect
 	github.com/gogo/protobuf v1.3.2
-	github.com/google/addlicense v0.0.0-20210428195630-6d92264d7170 // indirect
+	github.com/google/addlicense v0.0.0-20210428195630-6d92264d7170
 	github.com/gordonklaus/ineffassign v0.0.0-20200809085317-e36bfde3bb78
 	github.com/grpc-ecosystem/grpc-gateway v1.14.6
 	github.com/gyuho/gocovmerge v0.0.0-20171205171859-50c7e6afd535