diff --git a/.golangci.yml b/.golangci.yml
index a97e1bc11a..3ff2cd6281 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -62,7 +62,7 @@ run:
   # Define the Go version limit.
   # Mainly related to generics support since go1.18.
   # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.18
-  # go: '1.20'
+  # go: '1.21'
 
 # output configuration options
 output:
diff --git a/Dockerfile b/Dockerfile
index e6919ef7f6..07fd5ca62e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,7 +26,7 @@ ENV LANG en_US.UTF-8
 ENV LANGUAGE en_US.UTF-8
 ENV LC_ALL en_US.UTF-8
 
-FROM golang:1.20 as builder
+FROM golang:1.21 as builder
 RUN set -ex \
    && apt-get update --fix-missing \
    && apt-get install -qy --no-install-recommends \
diff --git a/Makefile b/Makefile
index c5712b21f3..840ac1ced5 100644
--- a/Makefile
+++ b/Makefile
@@ -45,11 +45,11 @@ all: install build
 install:
 	git lfs install
 	go mod download
-	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.53.3
+	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.54.2
 	go install github.com/spacemeshos/go-scale/scalegen@v1.1.10
 	go install go.uber.org/mock/mockgen@v0.2.0
-	go install gotest.tools/gotestsum@v1.10.0
-	go install honnef.co/go/tools/cmd/staticcheck@v0.4.3
+	go install gotest.tools/gotestsum@v1.10.1
+	go install honnef.co/go/tools/cmd/staticcheck@v0.4.5
 .PHONY: install
 
 build: go-spacemesh get-profiler
diff --git a/README.md b/README.md
index 5d7e5522fc..d4973738e6 100644
--- a/README.md
+++ b/README.md
@@ -86,7 +86,7 @@ Since the project uses Go Modules it is best to place the code **outside** your
 
 Building is supported on OS X, Linux, FreeBSD, and Windows.
 
-Install [Go 1.20 or later](https://golang.org/dl/) for your platform, if you haven't already.
+Install [Go 1.21 or later](https://golang.org/dl/) for your platform, if you haven't already.
 
 On Windows you need to install `make` via [msys2](https://www.msys2.org/), [MingGW-w64](http://mingw-w64.org/doku.php) or [mingw](https://chocolatey.org/packages/mingw)
 
diff --git a/appveyor.yml b/appveyor.yml
index 76f66bf9cc..74afb223ab 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,7 +5,7 @@ clone_folder: c:\gopath\src\github.com\spacemeshos\go-spacemesh\
 environment:
   GOPATH: c:\gopath
 
-stack: go 1.20
+stack: go 1.21
 
 before_build:
   - choco install make
diff --git a/beacon/beacon_test.go b/beacon/beacon_test.go
index 77997daddb..45ffcb4aab 100644
--- a/beacon/beacon_test.go
+++ b/beacon/beacon_test.go
@@ -500,7 +500,7 @@ func TestBeacon_BeaconsWithDatabase(t *testing.T) {
 	// clear out the in-memory map
 	// the database should still give us values
 	pd.mu.Lock()
-	pd.beacons = make(map[types.EpochID]types.Beacon)
+	clear(pd.beacons)
 	pd.mu.Unlock()
 
 	got, err = pd.GetBeacon(epoch3)
diff --git a/blocks/generator.go b/blocks/generator.go
index 9569687f59..7c686d2cf8 100644
--- a/blocks/generator.go
+++ b/blocks/generator.go
@@ -147,7 +147,7 @@ func (g *Generator) run() error {
 				out.Layer,
 				log.Int("num_proposals", len(out.Proposals)),
 			)
-			maxLayer = types.MaxLayer(maxLayer, out.Layer)
+			maxLayer = max(maxLayer, out.Layer)
 			_, err := g.processHareOutput(out)
 			if err != nil {
 				if errors.Is(err, errNodeHasBadMeshHash) {
diff --git a/blocks/utils.go b/blocks/utils.go
index 764e2c4a0a..58adf51f59 100644
--- a/blocks/utils.go
+++ b/blocks/utils.go
@@ -14,7 +14,6 @@ import (
 	"github.com/seehuhn/mt19937"
 
 	"github.com/spacemeshos/go-spacemesh/common/types"
-	"github.com/spacemeshos/go-spacemesh/common/util"
 	"github.com/spacemeshos/go-spacemesh/datastore"
 	"github.com/spacemeshos/go-spacemesh/events"
 	"github.com/spacemeshos/go-spacemesh/log"
@@ -207,7 +206,7 @@ func toUint64Slice(b []byte) []uint64 {
 	l := len(b)
 	var s []uint64
 	for i := 0; i < l; i += numByte {
-		s = append(s, binary.LittleEndian.Uint64(b[i:util.Min(l, i+numByte)]))
+		s = append(s, binary.LittleEndian.Uint64(b[i:min(l, i+numByte)]))
 	}
 	return s
 }
diff --git a/bootstrap.Dockerfile b/bootstrap.Dockerfile
index deec149eb4..d065f722a7 100644
--- a/bootstrap.Dockerfile
+++ b/bootstrap.Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.20 as builder
+FROM golang:1.21 as builder
 
 WORKDIR /src
 
diff --git a/common/types/beacon.go b/common/types/beacon.go
index 0549f30b2e..43f9bb4320 100644
--- a/common/types/beacon.go
+++ b/common/types/beacon.go
@@ -29,7 +29,7 @@ func (b Beacon) String() string { return b.Hex() }
 func (b Beacon) ShortString() string {
 	str := b.Hex()
 	l := len(str)
-	return Shorten(str[util.Min(2, l):], 10)
+	return Shorten(str[min(2, l):], 10)
 }
 
 // Bytes gets the byte representation of the underlying hash.
diff --git a/common/types/hashes.go b/common/types/hashes.go
index eb34a5e3f6..66f873ea72 100644
--- a/common/types/hashes.go
+++ b/common/types/hashes.go
@@ -51,7 +51,7 @@ func (h Hash20) String() string {
 // ShortString returns a the first 5 characters of the hash, for logging purposes.
 func (h Hash20) ShortString() string {
 	l := len(h.Hex())
-	return Shorten(h.Hex()[util.Min(2, l):], 10)
+	return Shorten(h.Hex()[min(2, l):], 10)
 }
 
 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
@@ -200,13 +200,13 @@ func (h Hash32) String() string {
 // ShortString returns the first 5 characters of the hash, for logging purposes.
 func (h Hash32) ShortString() string {
 	l := len(h.Hex())
-	return Shorten(h.Hex()[util.Min(2, l):], 10)
+	return Shorten(h.Hex()[min(2, l):], 10)
 }
 
 // Shorten shortens a string to a specified length.
 func Shorten(s string, maxlen int) string {
 	l := len(s)
-	return s[:util.Min(maxlen, l)]
+	return s[:min(maxlen, l)]
 }
 
 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
diff --git a/common/types/layer.go b/common/types/layer.go
index 5351401719..b7b66f077e 100644
--- a/common/types/layer.go
+++ b/common/types/layer.go
@@ -248,23 +248,3 @@ func NewLayer(layerIndex LayerID) *Layer {
 		blocks:  make([]*Block, 0, 3),
 	}
 }
-
-// MinLayer returns minimal nonzero layer.
-func MinLayer(i, j LayerID) LayerID {
-	if i == 0 {
-		return j
-	} else if j == 0 {
-		return i
-	} else if i < j {
-		return i
-	}
-	return j
-}
-
-// MaxLayer returns max layer.
-func MaxLayer(i, j LayerID) LayerID {
-	if i > j {
-		return i
-	}
-	return j
-}
diff --git a/common/util/compare.go b/common/util/compare.go
deleted file mode 100644
index 4429d89dba..0000000000
--- a/common/util/compare.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package util
-
-import "golang.org/x/exp/constraints"
-
-// Min returns the smaller of the two inputs, both of type int.
-func Min[T constraints.Ordered](a, b T) T {
-	if a < b {
-		return a
-	}
-	return b
-}
diff --git a/common/util/json.go b/common/util/json.go
index 6ccb3c475a..feb428e58e 100644
--- a/common/util/json.go
+++ b/common/util/json.go
@@ -157,15 +157,17 @@ func decodeNibble(in byte) uint64 {
 }
 
 func mapError(err error) error {
-	if err, ok := err.(*strconv.NumError); ok {
-		switch err.Err {
+	var numErr *strconv.NumError
+	if errors.As(err, &numErr) {
+		switch numErr.Err {
 		case strconv.ErrRange:
 			return ErrUint64Range
 		case strconv.ErrSyntax:
 			return ErrSyntax
 		}
 	}
-	if _, ok := err.(hex.InvalidByteError); ok {
+	var syntaxErr hex.InvalidByteError
+	if errors.As(err, &syntaxErr) {
 		return ErrSyntax
 	}
 	if errors.Is(err, hex.ErrLength) {
diff --git a/go.mod b/go.mod
index 1fb4b33e63..ed653fdc62 100644
--- a/go.mod
+++ b/go.mod
@@ -1,12 +1,12 @@
 module github.com/spacemeshos/go-spacemesh
 
-go 1.20
+go 1.21
 
 require (
 	cloud.google.com/go/storage v1.32.0
 	github.com/ALTree/bigfloat v0.2.0
 	github.com/benbjohnson/clock v1.3.5
-	github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230531032220-a757362a12e1
+	github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230824072557-45fdbaea2552
 	github.com/cosmos/btcutil v1.0.5
 	github.com/go-llsqlite/llsqlite v0.0.0-20230612031458-a9e271fe723a
 	github.com/gofrs/flock v0.8.1
@@ -20,7 +20,7 @@ require (
 	github.com/hashicorp/golang-lru/v2 v2.0.6
 	github.com/ipfs/go-ds-leveldb v0.5.0
 	github.com/ipfs/go-log/v2 v2.5.1
-	github.com/libp2p/go-libp2p v0.30.0
+	github.com/libp2p/go-libp2p v0.31.0
 	github.com/libp2p/go-libp2p-kad-dht v0.25.1
 	github.com/libp2p/go-libp2p-pubsub v0.9.3
 	github.com/libp2p/go-libp2p-record v0.2.0
@@ -28,7 +28,7 @@ require (
 	github.com/multiformats/go-multiaddr v0.11.0
 	github.com/multiformats/go-varint v0.0.7
 	github.com/natefinch/atomic v1.0.1
-	github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce
+	github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a
 	github.com/prometheus/client_golang v1.16.0
 	github.com/prometheus/common v0.44.0
 	github.com/pyroscope-io/pyroscope v0.37.2
@@ -56,9 +56,9 @@ require (
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d
 	google.golang.org/grpc v1.58.0
 	google.golang.org/protobuf v1.31.0
-	k8s.io/api v0.26.3
+	k8s.io/api v0.26.7
 	k8s.io/apimachinery v0.27.4
-	k8s.io/client-go v0.26.3
+	k8s.io/client-go v0.26.7
 	sigs.k8s.io/controller-runtime v0.14.6
 )
 
@@ -176,8 +176,8 @@ require (
 	github.com/prometheus/procfs v0.11.1 // indirect
 	github.com/pyroscope-io/dotnetdiag v1.2.1 // indirect
 	github.com/quic-go/qpack v0.4.0 // indirect
-	github.com/quic-go/qtls-go1-20 v0.3.2 // indirect
-	github.com/quic-go/quic-go v0.38.0 // indirect
+	github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
+	github.com/quic-go/quic-go v0.38.1 // indirect
 	github.com/quic-go/webtransport-go v0.5.3 // indirect
 	github.com/raulk/go-watchdog v1.3.0 // indirect
 	github.com/robfig/cron/v3 v3.0.1 // indirect
@@ -220,8 +220,8 @@ require (
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiextensions-apiserver v0.26.1 // indirect
-	k8s.io/component-base v0.26.1 // indirect
+	k8s.io/apiextensions-apiserver v0.26.7 // indirect
+	k8s.io/component-base v0.26.7 // indirect
 	k8s.io/klog/v2 v2.90.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
 	k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
diff --git a/go.sum b/go.sum
index a516d2b8e0..c7a4d4a0b8 100644
--- a/go.sum
+++ b/go.sum
@@ -78,14 +78,15 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
 github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
 github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA=
+github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM=
 github.com/c0mm4nd/go-ripemd v0.0.0-20200326052756-bd1759ad7d10 h1:wJ2csnFApV9G1jgh5KmYdxVOQMi+fihIggVTjcbM7ts=
 github.com/c0mm4nd/go-ripemd v0.0.0-20200326052756-bd1759ad7d10/go.mod h1:mYPR+a1fzjnHY3VFH5KL3PkEjMlVfGXP7c8rbWlkLJg=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230531032220-a757362a12e1 h1:yN5yGt1TwiTJhBPpYLW5FOnCYpF086dxdzBisrLhliE=
-github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230531032220-a757362a12e1/go.mod h1:5qllHIhMkPEWjIimDum42JtMj0P1Tn9x91XUceuPNjY=
+github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230824072557-45fdbaea2552 h1:Yp/OQYjMZRFYi4xJ1Z4mhU5k5yxVcyP/4qS8C+egROE=
+github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230824072557-45fdbaea2552/go.mod h1:y0x6w0fKnAgm/hBxDx2/0BDGw242LPEZ9eEq1foehCg=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -117,6 +118,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
 github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
 github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
+github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
@@ -141,16 +143,20 @@ github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 h1:S92OBrGuL
 github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05/go.mod h1:M9R1FoZ3y//hwwnJtO51ypFGwm8ZfpxPT/ZLtO1mcgQ=
 github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
 github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
+github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
 github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
 github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/felixge/fgprof v0.9.1 h1:E6FUJ2Mlv043ipLOCFqo8+cHo9MhQ203E2cdEK/isEs=
+github.com/felixge/fgprof v0.9.1/go.mod h1:7/HK6JFtFaARhIljgP2IV8rJLIoHDoOYoUphsnGvqxE=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
 github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
 github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
 github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
 github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
+github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@@ -172,6 +178,7 @@ github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
+github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -196,6 +203,7 @@ 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/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
+github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -261,6 +269,7 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
 github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
 github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
+github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -291,6 +300,7 @@ github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qK
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -311,6 +321,7 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
 github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
+github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
 github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
 github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
@@ -345,6 +356,7 @@ github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUN
 github.com/ipfs/go-ds-leveldb v0.5.0/go.mod h1:d3XG9RUDzQ6V4SHi8+Xgj9j1XuEk1z82lquxrVbml/Q=
 github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
 github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
+github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
 github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
 github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
 github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
@@ -366,6 +378,7 @@ github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
@@ -390,6 +403,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -401,8 +415,8 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y
 github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
 github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
 github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
-github.com/libp2p/go-libp2p v0.30.0 h1:9EZwFtJPFBcs/yJTnP90TpN1hgrT/EsFfM+OZuwV87U=
-github.com/libp2p/go-libp2p v0.30.0/go.mod h1:nr2g5V7lfftwgiJ78/HrID+pwvayLyqKCEirT2Y3Byg=
+github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHxYg=
+github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
 github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
 github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
 github.com/libp2p/go-libp2p-kad-dht v0.25.1 h1:ofFNrf6MMEy4vi3R1VbJ7LOcTn3Csh0cDcaWHTxtWNA=
@@ -416,6 +430,7 @@ github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvN
 github.com/libp2p/go-libp2p-routing-helpers v0.7.2 h1:xJMFyhQ3Iuqnk9Q2dYE1eUTzsah7NLw3Qs2zjUV78T0=
 github.com/libp2p/go-libp2p-routing-helpers v0.7.2/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
 github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
+github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
 github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
 github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
 github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
@@ -435,6 +450,7 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ
 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
 github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
@@ -495,6 +511,7 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
 github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
 github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
@@ -504,19 +521,21 @@ github.com/nullstyle/go-xdr v0.0.0-20180726165426-f4c839f75077/go.mod h1:sZZi9x5
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce h1:/pEpMk55wH0X+E5zedGEMOdLuWmV8P4+4W3+LZaM6kg=
-github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s=
+github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q=
+github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
 github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
+github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
 github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
 github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -555,10 +574,10 @@ github.com/pyroscope-io/pyroscope v0.37.2 h1:MOgLU/oO7VfV6jWqb0xoFH/YPSVbWD5pGsX
 github.com/pyroscope-io/pyroscope v0.37.2/go.mod h1:r4wq4ajJvN7g1OeXGyNvmwzBfQ+Tm5alYvmxqEQSTsc=
 github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
 github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/qtls-go1-20 v0.3.2 h1:rRgN3WfnKbyik4dBV8A6girlJVxGand/d+jVKbQq5GI=
-github.com/quic-go/qtls-go1-20 v0.3.2/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
-github.com/quic-go/quic-go v0.38.0 h1:T45lASr5q/TrVwt+jrVccmqHhPL2XuSyoCLVCpfOSLc=
-github.com/quic-go/quic-go v0.38.0/go.mod h1:MPCuRq7KBK2hNcfKj/1iD1BGuN3eAYMeNxp3T42LRUg=
+github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
+github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
+github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
 github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU=
 github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU=
 github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
@@ -568,6 +587,7 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -604,6 +624,7 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
@@ -719,6 +740,7 @@ go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
 go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU=
 go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1181,16 +1203,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU=
-k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE=
-k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
-k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
+k8s.io/api v0.26.7 h1:Lf4iEBEJb5OFNmawtBfSZV/UNi9riSJ0t1qdhyZqI40=
+k8s.io/api v0.26.7/go.mod h1:Vk9bMadzA49UHPmHB//lX7VRCQSXGoVwfLd3Sc1SSXI=
+k8s.io/apiextensions-apiserver v0.26.7 h1:L7ImW831auK1ZQBtNJPaG5qyrFxeISEBlgfZJfnaIPk=
+k8s.io/apiextensions-apiserver v0.26.7/go.mod h1:3DbZBfS3kO7/Jaj7qqzcBtPcKP0/KcklyAnk8zc+fs4=
 k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
 k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
-k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s=
-k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ=
-k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
-k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
+k8s.io/client-go v0.26.7 h1:hyU9aKHlwVOykgyxzGYkrDSLCc4+mimZVyUJjPyUn1E=
+k8s.io/client-go v0.26.7/go.mod h1:okYjy0jtq6sdeztALDvCh24tg4opOQS1XNvsJlERDAo=
+k8s.io/component-base v0.26.7 h1:uqsOyZh0Zqoaup8tmHa491D/CvgFdGUs+X2H/inNUKM=
+k8s.io/component-base v0.26.7/go.mod h1:CZe1HTmX/DQdeBrb9XYOXzs96jXth8ZbFvhLMsoJLUg=
 k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
 k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
 k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
diff --git a/hare/broker.go b/hare/broker.go
index 3a47b82835..b510aac1f8 100644
--- a/hare/broker.go
+++ b/hare/broker.go
@@ -6,6 +6,9 @@ import (
 	"fmt"
 	"sync"
 
+	"golang.org/x/exp/maps"
+	"golang.org/x/exp/slices"
+
 	"github.com/spacemeshos/go-spacemesh/codec"
 	"github.com/spacemeshos/go-spacemesh/common/types"
 	"github.com/spacemeshos/go-spacemesh/hare/config"
@@ -395,13 +398,9 @@ func (b *Broker) Register(ctx context.Context, id types.LayerID) (chan any, *Eli
 	if len(b.outbox) >= b.limit {
 		// unregister the earliest layer to make space for the new layer
 		// cannot call unregister here because unregister blocks and this would cause a deadlock
-		min := types.LayerID(0)
-		for lid := range b.outbox {
-			min = types.MinLayer(min, lid)
-		}
-		delete(b.outbox, min)
-		b.minDeleted = min
-		b.With().Info("unregistered layer due to maximum concurrent processes", min)
+		b.minDeleted = slices.Min(maps.Keys(b.outbox))
+		delete(b.outbox, b.minDeleted)
+		b.With().Info("unregistered layer due to maximum concurrent processes", b.minDeleted)
 	}
 	outboxCh := make(chan any, inboxCapacity)
 	b.outbox[id] = outboxCh
diff --git a/hare3/hare.go b/hare3/hare.go
index 643089aea3..25da02e4d8 100644
--- a/hare3/hare.go
+++ b/hare3/hare.go
@@ -213,9 +213,11 @@ func (h *Hare) Coins() <-chan WeakCoinOutput {
 func (h *Hare) Start() {
 	h.pubsub.Register(h.config.ProtocolName, h.Handler, pubsub.WithValidatorInline(true))
 	current := h.nodeclock.CurrentLayer() + 1
-	enabled := types.MaxLayer(current, h.config.EnableLayer)
-	enabled = types.MaxLayer(enabled, types.GetEffectiveGenesis()+1)
-	disabled := types.MinLayer(types.LayerID(math.MaxUint32), h.config.DisableLayer)
+	enabled := max(current, h.config.EnableLayer, types.GetEffectiveGenesis()+1)
+	disabled := types.LayerID(math.MaxUint32)
+	if h.config.DisableLayer > 0 {
+		disabled = h.config.DisableLayer
+	}
 	h.log.Info("started",
 		zap.Inline(&h.config),
 		zap.Uint32("enabled", enabled.Uint32()),
diff --git a/mesh/mesh.go b/mesh/mesh.go
index 92bc536b0d..368f6770e6 100644
--- a/mesh/mesh.go
+++ b/mesh/mesh.go
@@ -6,6 +6,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"math"
 	"sync"
 	"time"
 
@@ -69,6 +70,10 @@ func NewMesh(cdb *datastore.CachedDB, c layerClock, trtl system.Tortoise, exec *
 		conState:            state,
 		nextProcessedLayers: make(map[types.LayerID]struct{}),
 		missingBlocks:       make(chan []types.BlockID, 32),
+
+		pendingUpdates: struct {
+			min, max types.LayerID
+		}{min: math.MaxUint32},
 	}
 	msh.latestLayer.Store(types.LayerID(0))
 	msh.latestLayerInState.Store(types.LayerID(0))
@@ -232,7 +237,7 @@ func (msh *Mesh) setProcessedLayer(layerID types.LayerID) error {
 // the block in consensus, and reverts state before that layer
 // if such layer is found.
 func (msh *Mesh) ensureStateConsistent(ctx context.Context, results []result.Layer) error {
-	var changed types.LayerID
+	changed := types.LayerID(math.MaxUint32)
 	for _, layer := range results {
 		applied, err := layers.GetApplied(msh.cdb, layer.Layer)
 		if err != nil && errors.Is(err, sql.ErrNotFound) {
@@ -249,10 +254,10 @@ func (msh *Mesh) ensureStateConsistent(ctx context.Context, results []result.Lay
 				log.Stringer("expected", bid),
 				log.Stringer("applied", applied),
 			)
-			changed = types.MinLayer(changed, layer.Layer)
+			changed = min(changed, layer.Layer)
 		}
 	}
-	if changed == 0 {
+	if changed == math.MaxUint32 {
 		return nil
 	}
 	revert := changed.Sub(1)
@@ -284,18 +289,17 @@ func (msh *Mesh) ProcessLayer(ctx context.Context, lid types.LayerID) error {
 
 	msh.trtl.TallyVotes(ctx, lid)
 
-	if err := msh.setProcessedLayer(
-		lid); err != nil {
+	if err := msh.setProcessedLayer(lid); err != nil {
 		return err
 	}
 	results := msh.trtl.Updates()
-	pending := msh.pendingUpdates.min != 0
+	pending := msh.pendingUpdates.min != math.MaxUint32
 	if len(results) > 0 {
-		msh.pendingUpdates.min = types.MinLayer(msh.pendingUpdates.min, results[0].Layer)
-		msh.pendingUpdates.max = types.MaxLayer(msh.pendingUpdates.max, results[len(results)-1].Layer)
+		msh.pendingUpdates.min = min(msh.pendingUpdates.min, results[0].Layer)
+		msh.pendingUpdates.max = max(msh.pendingUpdates.max, results[len(results)-1].Layer)
 	}
 	next := msh.LatestLayerInState() + 1
-	if next < msh.pendingUpdates.min {
+	if msh.pendingUpdates.min != math.MaxUint32 && next < msh.pendingUpdates.min {
 		msh.pendingUpdates.min = next
 		pending = true
 	}
@@ -338,9 +342,9 @@ func (msh *Mesh) ProcessLayer(ctx context.Context, lid types.LayerID) error {
 	}
 	if len(missing) > 0 {
 		msh.pendingUpdates.min = applicable[len(applicable)-1].Layer
-		msh.pendingUpdates.max = types.MaxLayer(msh.pendingUpdates.min, msh.pendingUpdates.max)
+		msh.pendingUpdates.max = max(msh.pendingUpdates.min, msh.pendingUpdates.max)
 	} else {
-		msh.pendingUpdates.min = 0
+		msh.pendingUpdates.min = math.MaxUint32
 		msh.pendingUpdates.max = 0
 	}
 	return nil
diff --git a/proposals/util/util.go b/proposals/util/util.go
index be514310ab..bcd0f90a40 100644
--- a/proposals/util/util.go
+++ b/proposals/util/util.go
@@ -29,13 +29,6 @@ func CalcEligibleLayer(epochNumber types.EpochID, layersPerEpoch uint32, vrfSig
 	return epochNumber.FirstLayer().Add(uint32(eligibleLayerOffset))
 }
 
-func maxWeight(a, b uint64) uint64 {
-	if a > b {
-		return a
-	}
-	return b
-}
-
 func GetLegacyNumEligible(lid types.LayerID, weight, minWeight, totalWeight uint64, committeeSize, layersPerEpoch uint32) (uint32, error) {
 	legacyLayer := types.GetLegacyLayer()
 	if legacyLayer != 0 && legacyLayer >= lid.Uint32() {
@@ -49,7 +42,7 @@ func GetNumEligibleSlots(weight, minWeight, totalWeight uint64, committeeSize, l
 	if totalWeight == 0 {
 		return 0, ErrZeroTotalWeight
 	}
-	numEligible := weight * uint64(committeeSize) * uint64(layersPerEpoch) / maxWeight(minWeight, totalWeight) // TODO: ensure no overflow
+	numEligible := weight * uint64(committeeSize) * uint64(layersPerEpoch) / max(minWeight, totalWeight) // TODO: ensure no overflow
 	if numEligible == 0 {
 		numEligible = 1
 	}
diff --git a/syncer/state_syncer.go b/syncer/state_syncer.go
index ef57fd8f3b..8d263b44de 100644
--- a/syncer/state_syncer.go
+++ b/syncer/state_syncer.go
@@ -26,13 +26,6 @@ type peerOpinion struct {
 	peer        p2p.Peer
 }
 
-func minLayer(a, b types.LayerID) types.LayerID {
-	if a.Before(b) {
-		return a
-	}
-	return b
-}
-
 func (s *Syncer) stateSynced() bool {
 	current := s.ticker.CurrentLayer()
 	return current <= types.GetEffectiveGenesis() ||
@@ -55,8 +48,8 @@ func (s *Syncer) processLayers(ctx context.Context) error {
 		log.Stringer("last_synced", s.getLastSyncedLayer()),
 	)
 
-	start := minLayer(s.mesh.LatestLayerInState(), s.mesh.ProcessedLayer())
-	start = minLayer(start, s.getLastSyncedLayer())
+	start := min(s.mesh.LatestLayerInState(), s.mesh.ProcessedLayer())
+	start = min(start, s.getLastSyncedLayer())
 	if start == types.GetEffectiveGenesis() {
 		start = start.Add(1)
 	}
diff --git a/systest/Dockerfile b/systest/Dockerfile
index 1adffd78b6..bd12f679c9 100644
--- a/systest/Dockerfile
+++ b/systest/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.20-alpine as build
+FROM golang:1.21-alpine as build
 RUN apk add libc6-compat gcc musl-dev
 WORKDIR /build/
 
diff --git a/systest/Makefile b/systest/Makefile
index c543430671..87f24ba4e8 100644
--- a/systest/Makefile
+++ b/systest/Makefile
@@ -68,7 +68,7 @@ config: template
 
 .PHONY: gomplate
 gomplate:
-	@go install github.com/hairyhenderson/gomplate/v3/cmd/gomplate@latest
+	@go install github.com/hairyhenderson/gomplate/v4/cmd/gomplate@v4.0.0-pre-1
 
 .PHONY: run
 run: gomplate $(run_deps)
diff --git a/systest/tests/common.go b/systest/tests/common.go
index 975d5090d8..3a853296f6 100644
--- a/systest/tests/common.go
+++ b/systest/tests/common.go
@@ -310,20 +310,6 @@ func waitAll(tctx *testcontext.Context, cl *cluster.Cluster) error {
 	return eg.Wait()
 }
 
-func min(i, j int) int {
-	if i < j {
-		return i
-	}
-	return j
-}
-
-func maxLayer(i, j uint32) uint32 {
-	if i > j {
-		return i
-	}
-	return j
-}
-
 func nextFirstLayer(current, size uint32) uint32 {
 	if over := current % size; over != 0 {
 		current += size - over
diff --git a/systest/tests/steps_test.go b/systest/tests/steps_test.go
index 18a123e76b..191d3babf1 100644
--- a/systest/tests/steps_test.go
+++ b/systest/tests/steps_test.go
@@ -70,7 +70,7 @@ func TestStepShortDisconnect(t *testing.T) {
 	require.Greater(t, cl.Bootnodes(), 1)
 
 	var (
-		enable = maxLayer(currentLayer(tctx, t, cl.Client(0))+2, 9)
+		enable = max(currentLayer(tctx, t, cl.Client(0))+2, 9)
 		stop   = enable + 2
 	)
 	// make sure the first boot node is in the 2nd partition so the poet proof can be broadcast to both splits
diff --git a/systest/tests/timeskew_test.go b/systest/tests/timeskew_test.go
index c780255951..76d5d7bc30 100644
--- a/systest/tests/timeskew_test.go
+++ b/systest/tests/timeskew_test.go
@@ -21,7 +21,7 @@ func TestShortTimeskew(t *testing.T) {
 	require.NoError(t, err)
 
 	var (
-		enableSkew = maxLayer(currentLayer(tctx, t, cl.Client(0))+2, 9)
+		enableSkew = max(currentLayer(tctx, t, cl.Client(0))+2, 9)
 		stopSkew   = enableSkew + 2
 		stopTest   = stopSkew + 10
 		skewOffset = "-3s" // hare round is 2s
diff --git a/systest/tests/transactions_test.go b/systest/tests/transactions_test.go
index cb19a32738..c305bed039 100644
--- a/systest/tests/transactions_test.go
+++ b/systest/tests/transactions_test.go
@@ -16,7 +16,7 @@ import (
 func testTransactions(t *testing.T, tctx *testcontext.Context, cl *cluster.Cluster, sendFor uint32) {
 	var (
 		// start sending transactions after two layers or after genesis
-		first       = maxLayer(currentLayer(tctx, t, cl.Client(0))+2, 8)
+		first       = max(currentLayer(tctx, t, cl.Client(0))+2, 8)
 		stopSending = first + sendFor
 		batch       = 10
 		amount      = 100
diff --git a/tortoise/model/core.go b/tortoise/model/core.go
index 9af7f37ad4..f8eab435fc 100644
--- a/tortoise/model/core.go
+++ b/tortoise/model/core.go
@@ -203,10 +203,3 @@ func (b *beaconStore) GetBeacon(eid types.EpochID) (types.Beacon, error) {
 func (b *beaconStore) StoreBeacon(eid types.EpochID, beacon types.Beacon) {
 	b.beacons[eid] = beacon
 }
-
-func max(i, j uint32) uint32 {
-	if i > j {
-		return i
-	}
-	return j
-}
diff --git a/tortoise/recover.go b/tortoise/recover.go
index bf5d90135a..555580ef7d 100644
--- a/tortoise/recover.go
+++ b/tortoise/recover.go
@@ -57,7 +57,7 @@ func Recover(db *datastore.CachedDB, latest types.LayerID, beacon system.BeaconG
 		}
 	}
 	for lid := types.GetEffectiveGenesis().Add(1); !lid.After(layer); lid = lid.Add(1) {
-		if err := RecoverLayer(context.Background(), trtl, db, beacon, lid, types.MinLayer(layer, latest)); err != nil {
+		if err := RecoverLayer(context.Background(), trtl, db, beacon, lid, min(layer, latest)); err != nil {
 			return nil, fmt.Errorf("failed to load tortoise state at layer %d: %w", lid, err)
 		}
 	}
diff --git a/tortoise/state.go b/tortoise/state.go
index 3b3cd656ab..55f0aea455 100644
--- a/tortoise/state.go
+++ b/tortoise/state.go
@@ -435,7 +435,7 @@ func decodeVotes(evicted, blid types.LayerID, base *ballotInfo, exceptions types
 	from := base.layer
 	diff := map[types.LayerID]map[types.BlockID]headerWithSign{}
 	for _, header := range exceptions.Against {
-		from = types.MinLayer(from, header.LayerID)
+		from = min(from, header.LayerID)
 		layerdiff, exist := diff[header.LayerID]
 		if !exist {
 			layerdiff = map[types.BlockID]headerWithSign{}
@@ -448,7 +448,7 @@ func decodeVotes(evicted, blid types.LayerID, base *ballotInfo, exceptions types
 		layerdiff[header.ID] = headerWithSign{header, against}
 	}
 	for _, header := range exceptions.Support {
-		from = types.MinLayer(from, header.LayerID)
+		from = min(from, header.LayerID)
 		layerdiff, exist := diff[header.LayerID]
 		if !exist {
 			layerdiff = map[types.BlockID]headerWithSign{}
@@ -461,7 +461,7 @@ func decodeVotes(evicted, blid types.LayerID, base *ballotInfo, exceptions types
 		layerdiff[header.ID] = headerWithSign{header, support}
 	}
 	for _, lid := range exceptions.Abstain {
-		from = types.MinLayer(from, lid)
+		from = min(from, lid)
 		_, exist := diff[lid]
 		if !exist {
 			diff[lid] = map[types.BlockID]headerWithSign{}
diff --git a/tortoise/tortoise.go b/tortoise/tortoise.go
index 0c1e90de63..59e82719bc 100644
--- a/tortoise/tortoise.go
+++ b/tortoise/tortoise.go
@@ -360,7 +360,10 @@ func (t *turtle) onLayer(ctx context.Context, last types.LayerID) {
 		opinion := layer.opinion
 		layer.computeOpinion(t.Hdist, t.last)
 		if opinion != layer.opinion {
-			t.pending = types.MinLayer(t.pending, t.last)
+			if t.pending == 0 {
+				t.pending = t.last
+			}
+			t.pending = min(t.pending, t.last)
 		}
 
 		t.logger.Debug("initial local opinion",
@@ -415,7 +418,7 @@ func (t *turtle) countBallot(ballot *ballotInfo) error {
 
 func (t *turtle) verifyLayers() {
 	var (
-		verified           = maxLayer(t.evicted, types.GetEffectiveGenesis())
+		verified           = max(t.evicted, types.GetEffectiveGenesis())
 		nverified, changed types.LayerID
 	)
 	if t.isFull {
@@ -423,7 +426,7 @@ func (t *turtle) verifyLayers() {
 		vverified, vchanged := t.runVerifying()
 		if nverified == t.processed-1 && nverified == vverified {
 			t.switchModes()
-			changed = types.MinLayer(changed, vchanged)
+			changed = min(changed, vchanged)
 		}
 	} else {
 		nverified, changed = t.runVerifying()
@@ -431,17 +434,17 @@ func (t *turtle) verifyLayers() {
 		if !withinDistance(t.Hdist, nverified+1, t.last) {
 			fverified, fchanged := t.runFull()
 			nverified = fverified
-			changed = types.MinLayer(changed, fchanged)
+			changed = min(changed, fchanged)
 		}
 	}
 	for target := t.evicted.Add(1); target.Before(t.processed); target = target.Add(1) {
 		if nverified < target {
 			if target < t.verified {
-				changed = types.MinLayer(changed, target)
+				changed = min(changed, target)
 			}
 			break
 		} else if target > t.verified {
-			changed = types.MinLayer(changed, target)
+			changed = min(changed, target)
 		}
 		verified = target
 	}
@@ -451,8 +454,11 @@ func (t *turtle) verifyLayers() {
 		zap.Uint32("verified", verified.Uint32()),
 		zap.Uint32("changed", changed.Uint32()),
 	)
-	if changed != 0 {
-		t.pending = types.MinLayer(t.pending, changed)
+	if changed != math.MaxUint32 {
+		if t.pending == 0 {
+			t.pending = changed
+		}
+		t.pending = min(t.pending, changed)
 		t.onOpinionChange(changed, false)
 	}
 	t.verified = verified
@@ -461,13 +467,14 @@ func (t *turtle) verifyLayers() {
 
 func (t *turtle) runVerifying() (verified, changed types.LayerID) {
 	verified = t.evicted
+	changed = math.MaxUint32
 	for target := t.evicted.Add(1); target.Before(t.processed); target = target.Add(1) {
 		v, c := t.verifying.verify(t.logger, target)
 		if !v {
 			return verified, changed
 		}
 		if c {
-			changed = types.MinLayer(changed, target)
+			changed = min(changed, target)
 		}
 		verified = target
 	}
@@ -477,7 +484,7 @@ func (t *turtle) runVerifying() (verified, changed types.LayerID) {
 func (t *turtle) runFull() (verified, changed types.LayerID) {
 	if !t.isFull {
 		t.switchModes()
-		for counted := maxLayer(t.full.counted.Add(1), t.evicted.Add(1)); !counted.After(t.processed); counted = counted.Add(1) {
+		for counted := max(t.full.counted.Add(1), t.evicted.Add(1)); !counted.After(t.processed); counted = counted.Add(1) {
 			for _, ballot := range t.ballots[counted] {
 				t.full.countBallot(t.logger, ballot)
 			}
@@ -486,13 +493,14 @@ func (t *turtle) runFull() (verified, changed types.LayerID) {
 		}
 	}
 	verified = t.evicted
+	changed = math.MaxUint32
 	for target := t.evicted.Add(1); target.Before(t.processed); target = target.Add(1) {
 		v, c := t.full.verify(t.logger, target)
 		if !v {
 			return verified, changed
 		}
 		if c {
-			changed = types.MinLayer(changed, target)
+			changed = min(changed, target)
 		}
 		verified = target
 	}
@@ -585,7 +593,7 @@ func (t *turtle) onHareOutput(lid types.LayerID, bid types.BlockID) {
 }
 
 func (t *turtle) onOpinionChange(lid types.LayerID, early bool) {
-	var changed types.LayerID
+	changed := types.LayerID(math.MaxUint32)
 	for recompute := lid; !recompute.After(t.processed); recompute = recompute.Add(1) {
 		layer := t.layer(recompute)
 		opinion := layer.opinion
@@ -598,13 +606,16 @@ func (t *turtle) onOpinionChange(lid types.LayerID, early bool) {
 			zapBlocks(layer.blocks),
 		)
 		if opinion != layer.opinion {
-			changed = types.MinLayer(changed, recompute)
+			changed = min(changed, recompute)
 		} else if early {
 			break
 		}
 	}
-	if changed != 0 {
-		t.pending = types.MinLayer(t.pending, changed)
+	if changed != math.MaxUint32 {
+		if t.pending == 0 {
+			t.pending = changed
+		}
+		t.pending = min(t.pending, changed)
 		t.verifying.resetWeights(lid)
 		for target := lid.Add(1); !target.After(t.processed); target = target.Add(1) {
 			t.verifying.countVotes(t.logger, t.ballots[target])
diff --git a/tortoise/util.go b/tortoise/util.go
index ff8e1a606f..0e8487e5f6 100644
--- a/tortoise/util.go
+++ b/tortoise/util.go
@@ -5,8 +5,6 @@ import (
 
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
-
-	"github.com/spacemeshos/go-spacemesh/common/types"
 )
 
 const (
@@ -46,13 +44,6 @@ const (
 	reasonMissingData    voteReason = "missing data"
 )
 
-func maxLayer(i, j types.LayerID) types.LayerID {
-	if i.After(j) {
-		return i
-	}
-	return j
-}
-
 func verifyLayer(logger *zap.Logger, blocks []*blockInfo, getDecision func(*blockInfo) sign) (bool, bool) {
 	// order blocks by height in ascending order
 	// if there is a support before any abstain
diff --git a/txs/conservative_state_test.go b/txs/conservative_state_test.go
index e92969d4b3..867d3e6191 100644
--- a/txs/conservative_state_test.go
+++ b/txs/conservative_state_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"crypto/rand"
 	"errors"
+	"maps"
 	"math"
 	mrand "math/rand"
 	"sort"
@@ -14,7 +15,6 @@ import (
 	"github.com/libp2p/go-libp2p/core/peer"
 	"github.com/stretchr/testify/require"
 	"go.uber.org/mock/gomock"
-	"golang.org/x/exp/maps"
 
 	"github.com/spacemeshos/go-spacemesh/common/types"
 	"github.com/spacemeshos/go-spacemesh/genvm/sdk"
diff --git a/txs/utils.go b/txs/utils.go
index 65c9a8a099..5c12a8be3e 100644
--- a/txs/utils.go
+++ b/txs/utils.go
@@ -4,7 +4,6 @@ import (
 	"math/rand"
 
 	"github.com/spacemeshos/go-spacemesh/common/types"
-	"github.com/spacemeshos/go-spacemesh/common/util"
 	"github.com/spacemeshos/go-spacemesh/log"
 )
 
@@ -20,7 +19,7 @@ func ShuffleWithNonceOrder(
 	byAddrAndNonce map[types.Address][]*NanoTX,
 ) []types.TransactionID {
 	rng.Shuffle(len(ntxs), func(i, j int) { ntxs[i], ntxs[j] = ntxs[j], ntxs[i] })
-	total := util.Min(len(ntxs), numTXs)
+	total := min(len(ntxs), numTXs)
 	result := make([]types.TransactionID, 0, total)
 	packed := make(map[types.Address][]uint64)
 	for _, ntx := range ntxs[:total] {