diff --git a/catchup/universalFetcher.go b/catchup/universalFetcher.go
index 926c85bb48..4e4d920c23 100644
--- a/catchup/universalFetcher.go
+++ b/catchup/universalFetcher.go
@@ -219,13 +219,19 @@ type HTTPFetcher struct {
// getBlockBytes gets a block.
// Core piece of FetcherClient interface
func (hf *HTTPFetcher) getBlockBytes(ctx context.Context, r basics.Round) (data []byte, err error) {
- parsedURL, err := network.ParseHostOrURL(hf.rootURL)
- if err != nil {
- return nil, err
+ var blockURL string
+
+ if network.IsMultiaddr(hf.rootURL) {
+ blockURL = rpcs.FormatBlockQuery(uint64(r), "", hf.net)
+ } else {
+ if parsedURL, err0 := network.ParseHostOrURL(hf.rootURL); err0 == nil {
+ parsedURL.Path = rpcs.FormatBlockQuery(uint64(r), parsedURL.Path, hf.net)
+ blockURL = parsedURL.String()
+ } else {
+ return nil, err0
+ }
}
- parsedURL.Path = rpcs.FormatBlockQuery(uint64(r), parsedURL.Path, hf.net)
- blockURL := parsedURL.String()
hf.log.Debugf("block GET %#v peer %#v %T", blockURL, hf.peer, hf.peer)
request, err := http.NewRequest("GET", blockURL, nil)
if err != nil {
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index b8ecd76cac..2e3786588e 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -834,8 +834,13 @@ func OpcodesByVersion(version uint64) []OpSpec {
}
}
result := maps.Values(subv)
- slices.SortFunc(result, func(a, b OpSpec) bool {
- return a.Opcode < b.Opcode
+ slices.SortFunc(result, func(a, b OpSpec) int {
+ if a.Opcode == b.Opcode {
+ return 0
+ } else if a.Opcode > b.Opcode {
+ return 1
+ }
+ return -1
})
return result
}
diff --git a/go.mod b/go.mod
index 9ebaa462bd..d106515fe1 100644
--- a/go.mod
+++ b/go.mod
@@ -30,21 +30,21 @@ require (
github.com/jmoiron/sqlx v1.2.0
github.com/karalabe/usb v0.0.2
github.com/labstack/echo/v4 v4.9.1
- github.com/libp2p/go-libp2p v0.29.1
+ github.com/libp2p/go-libp2p v0.32.2
github.com/libp2p/go-libp2p-kad-dht v0.24.3
- github.com/libp2p/go-libp2p-pubsub v0.9.3
+ github.com/libp2p/go-libp2p-pubsub v0.10.0
github.com/libp2p/go-yamux/v4 v4.0.1
github.com/mattn/go-sqlite3 v1.14.16
- github.com/miekg/dns v1.1.55
- github.com/multiformats/go-multiaddr v0.10.1
+ github.com/miekg/dns v1.1.56
+ github.com/multiformats/go-multiaddr v0.12.0
github.com/multiformats/go-multiaddr-dns v0.3.1
github.com/olivere/elastic v6.2.14+incompatible
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.14.0
- golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
- golang.org/x/sync v0.3.0
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d
+ golang.org/x/sync v0.4.0
golang.org/x/sys v0.13.0
golang.org/x/text v0.13.0
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009
@@ -81,17 +81,16 @@ require (
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
- github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/invopop/yaml v0.1.0 // indirect
github.com/ipfs/boxo v0.10.0 // indirect
@@ -104,7 +103,7 @@ require (
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmespath/go-jmespath v0.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
@@ -119,11 +118,11 @@ require (
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
- github.com/libp2p/go-reuseport v0.3.0 // indirect
+ github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
@@ -137,10 +136,10 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
- github.com/opencontainers/runtime-spec v1.0.2 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
+ github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
@@ -152,10 +151,9 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-19 v0.3.3 // indirect
- github.com/quic-go/qtls-go1-20 v0.2.3 // indirect
- github.com/quic-go/quic-go v0.36.3 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.4 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
@@ -169,16 +167,16 @@ require (
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
- go.uber.org/atomic v1.11.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.24.0 // indirect
- golang.org/x/mod v0.12.0 // indirect
+ go.uber.org/zap v1.26.0 // indirect
+ golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
- golang.org/x/tools v0.11.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
diff --git a/go.sum b/go.sum
index 15a6c0d6b8..45f0add778 100644
--- a/go.sum
+++ b/go.sum
@@ -191,8 +191,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -229,8 +227,8 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA=
-github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -255,12 +253,12 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU=
-github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
+github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
@@ -321,8 +319,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -352,16 +350,16 @@ 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.29.1 h1:yNeg6XgP8gbdc4YSrwiIt5T1TGOrVjH8dzl8h0GIOfQ=
-github.com/libp2p/go-libp2p v0.29.1/go.mod h1:20El+LLy3/YhdUYIvGbLnvVJN32nMdqY6KXBENRAfLY=
+github.com/libp2p/go-libp2p v0.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
+github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
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.24.3 h1:VjxtDVWaaf4UFjGBf+yl2JCiGaHx7+ctAUa9oJCR3QE=
github.com/libp2p/go-libp2p-kad-dht v0.24.3/go.mod h1:BShPzRbK6+fN3hk8a0WGAYKpb8m4k+DtchkqouGTrSg=
github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
-github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo=
-github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc=
+github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
+github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
@@ -371,8 +369,8 @@ github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
-github.com/libp2p/go-reuseport v0.3.0 h1:iiZslO5byUYZEg9iCwJGf5h+sf1Agmqx2V2FDjPyvUw=
-github.com/libp2p/go-reuseport v0.3.0/go.mod h1:laea40AimhtfEqysZ71UpYj4S+R9VpH8PgqLo7L+SwI=
+github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
+github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
@@ -394,8 +392,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
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=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
@@ -408,8 +406,8 @@ github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQ
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -439,8 +437,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.10.1 h1:HghtFrWyZEPrpTvgAMFJi6gFdgHfs2cb0pyfDsk+lqU=
-github.com/multiformats/go-multiaddr v0.10.1/go.mod h1:jLEZsA61rwWNZQTHHnqq2HNa+4os/Hz54eqiRnsRqYQ=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@@ -452,8 +450,8 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
@@ -468,13 +466,14 @@ github.com/olivere/elastic v6.2.14+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGe
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
-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/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
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/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
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=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
@@ -508,14 +507,12 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
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-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=
-github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
-github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=
-github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
-github.com/quic-go/quic-go v0.36.3 h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834=
-github.com/quic-go/quic-go v0.36.3/go.mod h1:qxQumdeKw5GmWs1OsTZZnOxzSI+RJWuhf1O8FN35L2o=
-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/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.4 h1:PelfiuG7wXEffUT2yceiqz5V6Pc0TA5ruOd1LcmFc1s=
+github.com/quic-go/quic-go v0.39.4/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -634,13 +631,14 @@ go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLk
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -648,8 +646,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -667,8 +665,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
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=
@@ -681,8 +679,8 @@ 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/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -722,8 +720,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
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/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -793,11 +791,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
-golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
-golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
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=
diff --git a/network/addr.go b/network/addr.go
index 1e2b04a447..c12a09a4af 100644
--- a/network/addr.go
+++ b/network/addr.go
@@ -64,6 +64,15 @@ func ParseHostOrURL(addr string) (*url.URL, error) {
return parsed, err /* return original err, not our prefix altered try */
}
+// IsMultiaddr returns true if the provided string is a valid multiaddr.
+func IsMultiaddr(addr string) bool {
+ if strings.HasPrefix(addr, "/") && !strings.HasPrefix(addr, "//") { // multiaddr starts with '/' but not '//' which is possible for scheme relative URLS
+ _, err := multiaddr.NewMultiaddr(addr)
+ return err == nil
+ }
+ return false
+}
+
// ParseHostOrURLOrMultiaddr returns an error if it could not parse the provided
// string as a valid "host:port", full URL, or multiaddr. If no error, it returns
// a host:port address, or a multiaddr.
diff --git a/network/addr_test.go b/network/addr_test.go
index 377fe72a91..eec2eccc36 100644
--- a/network/addr_test.go
+++ b/network/addr_test.go
@@ -124,6 +124,7 @@ func TestParseHostURLOrMultiaddr(t *testing.T) {
v, err := ParseHostOrURLOrMultiaddr(addr)
require.NoError(t, err)
require.Equal(t, addr, v)
+ require.True(t, IsMultiaddr(addr))
})
}
@@ -131,6 +132,7 @@ func TestParseHostURLOrMultiaddr(t *testing.T) {
t.Run(addr, func(t *testing.T) {
_, err := ParseHostOrURLOrMultiaddr(addr)
require.Error(t, err)
+ require.False(t, IsMultiaddr(addr))
})
}
diff --git a/network/p2p/capabilities_test.go b/network/p2p/capabilities_test.go
index 65db0433c9..d6694e5fb2 100644
--- a/network/p2p/capabilities_test.go
+++ b/network/p2p/capabilities_test.go
@@ -96,6 +96,12 @@ func setupDHTHosts(t *testing.T, numHosts int) []*dht.IpfsDHT {
for _, h := range hosts {
ht, err := algodht.MakeDHT(context.Background(), h, "devtestnet", cfg, func() []peer.AddrInfo { return bootstrapPeers })
require.NoError(t, err)
+ // this is a workaround for the following issue
+ // "failed to negotiate security protocol: error reading handshake message: noise: message is too short"
+ // it appears simultenous connectino attempts (dht.New() attempts to connect) causes this handshake error.
+ // https://github.com/libp2p/go-libp2p-noise/issues/70
+ time.Sleep(200 * time.Millisecond)
+
err = ht.Bootstrap(context.Background())
require.NoError(t, err)
dhts = append(dhts, ht)
@@ -150,6 +156,12 @@ func setupCapDiscovery(t *testing.T, numHosts int, numBootstrapPeers int) []*Cap
}
ht, err := algodht.MakeDHT(context.Background(), h, "devtestnet", cfg, func() []peer.AddrInfo { return bp })
require.NoError(t, err)
+ // this is a workaround for the following issue
+ // "failed to negotiate security protocol: error reading handshake message: noise: message is too short"
+ // it appears simultenous connectino attempts (dht.New() attempts to connect) causes this handshake error.
+ // https://github.com/libp2p/go-libp2p-noise/issues/70
+ time.Sleep(200 * time.Millisecond)
+
disc, err := algodht.MakeDiscovery(ht)
require.NoError(t, err)
cd := &CapabilitiesDiscovery{
diff --git a/network/p2p/dnsaddr/resolve.go b/network/p2p/dnsaddr/resolve.go
index 176d62f946..56caa84f4b 100644
--- a/network/p2p/dnsaddr/resolve.go
+++ b/network/p2p/dnsaddr/resolve.go
@@ -30,7 +30,7 @@ func isDnsaddr(maddr multiaddr.Multiaddr) bool {
}
// Iterate runs through the resolvable dnsaddrs in the tree using the resolveController and invokes f for each dnsaddr node lookup
-func Iterate(initial multiaddr.Multiaddr, controller *MultiaddrDNSResolveController, f func(dnsaddr multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error) error {
+func Iterate(initial multiaddr.Multiaddr, controller ResolveController, f func(dnsaddr multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error) error {
resolver := controller.Resolver()
if resolver == nil {
return errors.New("passed controller has no resolvers Iterate")
@@ -64,7 +64,7 @@ func Iterate(initial multiaddr.Multiaddr, controller *MultiaddrDNSResolveControl
// Any further dnsaddrs will be looked up until all TXT records have been fetched,
// and the full list of resulting Multiaddrs is returned.
// It uses the MultiaddrDNSResolveController to cycle through DNS resolvers on failure.
-func MultiaddrsFromResolver(domain string, controller *MultiaddrDNSResolveController) ([]multiaddr.Multiaddr, error) {
+func MultiaddrsFromResolver(domain string, controller ResolveController) ([]multiaddr.Multiaddr, error) {
dnsaddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/dnsaddr/%s", domain))
if err != nil {
return nil, fmt.Errorf("unable to construct multiaddr for %s : %v", domain, err)
diff --git a/network/p2p/dnsaddr/resolveController.go b/network/p2p/dnsaddr/resolveController.go
index 73a46243d0..ff606b39a1 100644
--- a/network/p2p/dnsaddr/resolveController.go
+++ b/network/p2p/dnsaddr/resolveController.go
@@ -17,15 +17,29 @@
package dnsaddr
import (
+ "context"
+
+ "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
log "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/tools/network"
)
+// Resolver is an interface for resolving dnsaddrs
+type Resolver interface {
+ Resolve(ctx context.Context, maddr multiaddr.Multiaddr) ([]multiaddr.Multiaddr, error)
+}
+
+// ResolveController is an interface for cycling through resolvers
+type ResolveController interface {
+ Resolver() Resolver
+ NextResolver() Resolver
+}
+
// MultiaddrDNSResolveController returns a madns.Resolver, cycling through underlying net.Resolvers
type MultiaddrDNSResolveController struct {
- resolver *madns.Resolver
+ resolver Resolver
nextResolvers []func() *madns.Resolver
controller network.ResolveController
}
@@ -45,7 +59,7 @@ func NewMultiaddrDNSResolveController(secure bool, fallbackDNSResolverAddress st
}
// NextResolver applies the nextResolvers functions in order and returns the most recent result
-func (c *MultiaddrDNSResolveController) NextResolver() *madns.Resolver {
+func (c *MultiaddrDNSResolveController) NextResolver() Resolver {
if len(c.nextResolvers) == 0 {
c.resolver = nil
} else {
@@ -56,7 +70,7 @@ func (c *MultiaddrDNSResolveController) NextResolver() *madns.Resolver {
}
// Resolver returns the current resolver, invokes NextResolver if the resolver is nil
-func (c *MultiaddrDNSResolveController) Resolver() *madns.Resolver {
+func (c *MultiaddrDNSResolveController) Resolver() Resolver {
if c.resolver == nil {
c.resolver = c.NextResolver()
}
diff --git a/network/p2p/http.go b/network/p2p/http.go
new file mode 100644
index 0000000000..1f39fa56c2
--- /dev/null
+++ b/network/p2p/http.go
@@ -0,0 +1,46 @@
+// Copyright (C) 2019-2024 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package p2p
+
+import (
+ "net/http"
+
+ "github.com/libp2p/go-libp2p"
+ "github.com/libp2p/go-libp2p/core/peer"
+ libp2phttp "github.com/libp2p/go-libp2p/p2p/http"
+)
+
+// MakeHTTPClient creates a http.Client that uses libp2p transport for a goven protocol and peer address.
+func MakeHTTPClient(protocolID string, addrInfo peer.AddrInfo) (http.Client, error) {
+ clientStreamHost, err := libp2p.New(libp2p.NoListenAddrs)
+ if err != nil {
+ return http.Client{}, err
+ }
+
+ client := libp2phttp.Host{StreamHost: clientStreamHost}
+
+ // Do not use client.NamespacedClient to prevent it making connection to a well-known handler
+ // to make a NamespaceRoundTripper that limits to specific URL paths.
+ // First, we do not want make requests when listing peers (the main MakeHTTPClient invoker).
+ // Secondly, this makes unit testing easier - no need to register fake handlers.
+ rt, err := client.NewConstrainedRoundTripper(addrInfo)
+ if err != nil {
+ return http.Client{}, err
+ }
+
+ return http.Client{Transport: rt}, nil
+}
diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go
index 7450f34794..99f537ed36 100644
--- a/network/p2p/p2p.go
+++ b/network/p2p/p2p.go
@@ -75,6 +75,9 @@ type serviceImpl struct {
// AlgorandWsProtocol defines a libp2p protocol name for algorand's websockets messages
const AlgorandWsProtocol = "/algorand-ws/1.0.0"
+// AlgorandP2pHTTPProtocol defines a libp2p protocol name for algorand's http over p2p messages
+const AlgorandP2pHTTPProtocol = "/algorand-http/1.0.0"
+
const dialTimeout = 30 * time.Second
// MakeHost creates a libp2p host but does not start listening.
diff --git a/network/p2p/peerID.go b/network/p2p/peerID.go
index 382258ac22..8ca584cbe8 100644
--- a/network/p2p/peerID.go
+++ b/network/p2p/peerID.go
@@ -39,6 +39,10 @@ const DefaultPrivKeyPath = "peerIDPrivKey.pem"
// PeerID is a string representation of a peer's public key, primarily used to avoid importing libp2p into packages that shouldn't need it
type PeerID string
+func (id PeerID) String() string {
+ return peer.ID(id).String()
+}
+
// GetPrivKey manages loading and creation of private keys for network PeerIDs
// It prioritizes, in this order:
// 1. user supplied path to privKey
diff --git a/network/p2p/streams.go b/network/p2p/streams.go
index 4a7a2d8e01..0e5c59d50c 100644
--- a/network/p2p/streams.go
+++ b/network/p2p/streams.go
@@ -73,7 +73,17 @@ func (n *streamManager) streamHandler(stream network.Stream) {
n.log.Infof("Failed to check old stream with %s: %v", remotePeer, err)
}
n.streams[stream.Conn().RemotePeer()] = stream
- n.handler(n.ctx, remotePeer, stream, true)
+
+ // streamHandler is supposed to be called for accepted streams, so we expect incoming here
+ incoming := stream.Stat().Direction == network.DirInbound
+ if !incoming {
+ if stream.Stat().Direction == network.DirUnknown {
+ n.log.Warnf("Unknown direction for a steam %s to/from %s", stream.ID(), remotePeer)
+ } else {
+ n.log.Warnf("Unexpected outgoing sream in streamHandler for connection %s (%s): %s vs %s stream", stream.Conn().ID(), remotePeer, stream.Conn().Stat().Direction, stream.Stat().Direction.String())
+ }
+ }
+ n.handler(n.ctx, remotePeer, stream, incoming)
return
}
// otherwise, the old stream is still open, so we can close the new one
@@ -82,7 +92,16 @@ func (n *streamManager) streamHandler(stream network.Stream) {
}
// no old stream
n.streams[stream.Conn().RemotePeer()] = stream
- n.handler(n.ctx, remotePeer, stream, true)
+ // streamHandler is supposed to be called for accepted streams, so we expect incoming here
+ incoming := stream.Stat().Direction == network.DirInbound
+ if !incoming {
+ if stream.Stat().Direction == network.DirUnknown {
+ n.log.Warnf("streamHandler: unknown direction for a steam %s to/from %s", stream.ID(), remotePeer)
+ } else {
+ n.log.Warnf("Unexpected outgoing sream in streamHandler for connection %s (%s): %s vs %s stream", stream.Conn().ID(), remotePeer, stream.Conn().Stat().Direction, stream.Stat().Direction.String())
+ }
+ }
+ n.handler(n.ctx, remotePeer, stream, incoming)
}
// Connected is called when a connection is opened
@@ -95,8 +114,13 @@ func (n *streamManager) Connected(net network.Network, conn network.Conn) {
return
}
+ needUnlock := true
n.streamsLock.Lock()
- defer n.streamsLock.Unlock()
+ defer func() {
+ if needUnlock {
+ n.streamsLock.Unlock()
+ }
+ }()
_, ok := n.streams[remotePeer]
if ok {
return // there's already an active stream with this peer for our protocol
@@ -107,9 +131,23 @@ func (n *streamManager) Connected(net network.Network, conn network.Conn) {
n.log.Infof("Failed to open stream to %s: %v", remotePeer, err)
return
}
-
n.streams[remotePeer] = stream
- n.handler(n.ctx, remotePeer, stream, false)
+
+ // release the lock to let handler do its thing
+ // otherwise reading/writing to the stream will deadlock
+ needUnlock = false
+ n.streamsLock.Unlock()
+
+ // a new stream created above, expected direction is outbound
+ incoming := stream.Stat().Direction == network.DirInbound
+ if incoming {
+ n.log.Warnf("Unexpected incoming sream in streamHandler for connection %s (%s): %s vs %s stream", stream.Conn().ID(), remotePeer, stream.Conn().Stat().Direction, stream.Stat().Direction.String())
+ } else {
+ if stream.Stat().Direction == network.DirUnknown {
+ n.log.Warnf("Connected: unknown direction for a steam %s to/from %s", stream.ID(), remotePeer)
+ }
+ }
+ n.handler(n.ctx, remotePeer, stream, incoming)
}
// Disconnected is called when a connection is closed
diff --git a/network/p2pNetwork.go b/network/p2pNetwork.go
index f54c5de89c..4cfec68bad 100644
--- a/network/p2pNetwork.go
+++ b/network/p2pNetwork.go
@@ -32,10 +32,12 @@ import (
"github.com/algorand/go-algorand/network/p2p/peerstore"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-deadlock"
+ "github.com/gorilla/mux"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
+ libp2phttp "github.com/libp2p/go-libp2p/p2p/http"
manet "github.com/multiformats/go-multiaddr/net"
)
@@ -69,13 +71,19 @@ type P2PNetwork struct {
bootstrapper bootstrapper
nodeInfo NodeInfo
+ pstore *peerstore.PeerStore
+ httpServer libp2phttp.Host
+
+ p2phttpMux *mux.Router
+ p2phttpMuxRegistarOnce sync.Once
}
type bootstrapper struct {
- cfg config.Local
- networkID protocol.NetworkID
- phonebookPeers []*peer.AddrInfo
- started bool
+ cfg config.Local
+ networkID protocol.NetworkID
+ phonebookPeers []*peer.AddrInfo
+ resolveControler dnsaddr.ResolveController
+ started bool
}
func (b *bootstrapper) start() {
@@ -103,16 +111,15 @@ func (b *bootstrapper) BootstrapFunc() []peer.AddrInfo {
return addrs
}
- return getBootstrapPeers(b.cfg, b.networkID)
+ return getBootstrapPeers(b.cfg, b.networkID, b.resolveControler)
}
// getBootstrapPeers looks up a list of Multiaddrs strings from the dnsaddr records at the primary
// SRV record domain.
-func getBootstrapPeers(cfg config.Local, network protocol.NetworkID) []peer.AddrInfo {
+func getBootstrapPeers(cfg config.Local, network protocol.NetworkID, controller dnsaddr.ResolveController) []peer.AddrInfo {
var addrs []peer.AddrInfo
bootstraps := cfg.DNSBootstrapArray(network)
for _, dnsBootstrap := range bootstraps {
- controller := dnsaddr.NewMultiaddrDNSResolveController(cfg.DNSSecuritySRVEnforced(), "")
resolvedAddrs, err := dnsaddr.MultiaddrsFromResolver(dnsBootstrap.PrimarySRVBootstrap, controller)
if err != nil {
continue
@@ -163,6 +170,8 @@ func NewP2PNetwork(log logging.Logger, cfg config.Local, datadir string, phonebo
wsPeersToIDs: make(map[*wsPeer]peer.ID),
peerStats: make(map[peer.ID]*p2pPeerStats),
nodeInfo: node,
+ pstore: pstore,
+ p2phttpMux: mux.NewRouter(),
}
net.ctx, net.ctxCancel = context.WithCancel(context.Background())
net.handler = msgHandler{
@@ -191,9 +200,10 @@ func NewP2PNetwork(log logging.Logger, cfg config.Local, datadir string, phonebo
}
bootstrapper := &bootstrapper{
- cfg: cfg,
- networkID: networkID,
- phonebookPeers: addrInfo,
+ cfg: cfg,
+ networkID: networkID,
+ phonebookPeers: addrInfo,
+ resolveControler: dnsaddr.NewMultiaddrDNSResolveController(cfg.DNSSecuritySRVEnforced(), ""),
}
if cfg.EnableDHTProviders {
@@ -205,6 +215,10 @@ func NewP2PNetwork(log logging.Logger, cfg config.Local, datadir string, phonebo
net.capabilitiesDiscovery = disc
}
+ net.httpServer = libp2phttp.Host{
+ StreamHost: h,
+ }
+
err = net.setup()
if err != nil {
return nil, err
@@ -250,6 +264,9 @@ func (n *P2PNetwork) Start() error {
go n.handler.messageHandlerThread(&n.wg, n.wsPeersConnectivityCheckTicker.C, n)
}
+ n.wg.Add(1)
+ go n.httpdThread()
+
n.wg.Add(1)
go n.broadcaster.broadcastThread(&n.wg, n)
n.service.DialPeersUntilTargetCount(n.config.GossipFanout)
@@ -279,6 +296,7 @@ func (n *P2PNetwork) Stop() {
n.ctxCancel()
n.service.Close()
n.bootstrapper.stop()
+ n.httpServer.Close()
n.wg.Wait()
}
@@ -316,6 +334,15 @@ func (n *P2PNetwork) meshThread() {
}
}
+func (n *P2PNetwork) httpdThread() {
+ defer n.wg.Done()
+ err := n.httpServer.Serve()
+ if err != nil {
+ n.log.Errorf("Error serving libp2phttp: %v", err)
+ return
+ }
+}
+
// GetGenesisID implements GossipNode
func (n *P2PNetwork) GetGenesisID() string {
return n.genesisID
@@ -407,6 +434,10 @@ func (n *P2PNetwork) DisconnectPeers() {
// RegisterHTTPHandler path accepts gorilla/mux path annotations
func (n *P2PNetwork) RegisterHTTPHandler(path string, handler http.Handler) {
+ n.p2phttpMux.Handle(path, handler)
+ n.p2phttpMuxRegistarOnce.Do(func() {
+ n.httpServer.SetHTTPHandlerAtPath(p2p.AlgorandP2pHTTPProtocol, "/", n.p2phttpMux)
+ })
}
// RequestConnectOutgoing asks the system to actually connect to peers.
@@ -417,13 +448,97 @@ func (n *P2PNetwork) RequestConnectOutgoing(replace bool, quit <-chan struct{})
// GetPeers returns a list of Peers we could potentially send a direct message to.
func (n *P2PNetwork) GetPeers(options ...PeerOption) []Peer {
- // currently returns same list of peers for all PeerOption filters.
peers := make([]Peer, 0)
- n.wsPeersLock.RLock()
- for _, peer := range n.wsPeers {
- peers = append(peers, Peer(peer))
+ for _, option := range options {
+ switch option {
+ case PeersConnectedOut:
+ n.wsPeersLock.RLock()
+ for _, peer := range n.wsPeers {
+ if peer.outgoing {
+ peers = append(peers, Peer(peer))
+ }
+ }
+ n.wsPeersLock.RUnlock()
+ case PeersPhonebookRelays:
+ // TODO: query peerstore for PhoneBookEntryRelayRole
+ // TODO: currently peerstore is not populated in a way to store roles
+ // return all nodes at the moment
+
+ // // return copy of phonebook, which probably also contains peers we're connected to, but if it doesn't maybe we shouldn't be making new connections to those peers (because they disappeared from the directory)
+ // addrs := n.pstore.GetAddresses(1000, PhoneBookEntryRelayRole)
+ // for _, addr := range addrs {
+ // peerCore := makePeerCore(n.ctx, n, n.log, n.handler.readBuffer, addr, n.GetRoundTripper(nil), "" /*origin address*/)
+ // peers = append(peers, &peerCore)
+ // }
+
+ // temporary return all nodes
+ n.wsPeersLock.RLock()
+ for _, peer := range n.wsPeers {
+ peers = append(peers, Peer(peer))
+ }
+ n.wsPeersLock.RUnlock()
+
+ case PeersPhonebookArchivalNodes:
+ // query known archvial nodes from DHT if enabled
+ if n.config.EnableDHTProviders {
+ const nodesToFind = 5
+ info, err := n.capabilitiesDiscovery.PeersForCapability(p2p.Archival, nodesToFind)
+ if err != nil {
+ n.log.Warnf("Error getting archival nodes from capabilities discovery: %v", err)
+ return peers
+ }
+ n.log.Debugf("Got %d archival node(s) from DHT", len(info))
+ for _, addrInfo := range info {
+ info := addrInfo
+ mas, err := peer.AddrInfoToP2pAddrs(&info)
+ if err != nil {
+ n.log.Warnf("Archival AddrInfo conversion error: %v", err)
+ continue
+ }
+ if len(mas) == 0 {
+ n.log.Warnf("Archival AddrInfo: empty multiaddr for : %v", addrInfo)
+ continue
+ }
+ addr := mas[0].String()
+ client, err := p2p.MakeHTTPClient(p2p.AlgorandP2pHTTPProtocol, addrInfo)
+ if err != nil {
+ n.log.Warnf("MakeHTTPClient failed: %v", err)
+ continue
+ }
+
+ peerCore := makePeerCoreWithClient(
+ n.ctx, n, n.log, n.handler.readBuffer,
+ addr /*rootURL*/, client, "", /*origin address*/
+ )
+ peers = append(peers, &peerCore)
+ }
+ if n.log.GetLevel() >= logging.Debug && len(peers) > 0 {
+ addrs := make([]string, 0, len(peers))
+ for _, peer := range peers {
+ addrs = append(addrs, peer.(*wsPeerCore).rootURL)
+ }
+ n.log.Debugf("Archival node(s) from DHT: %v", addrs)
+ }
+ }
+ case PeersPhonebookArchivers:
+ // TODO: remove after merging with master
+ // temporary return all nodes
+ n.wsPeersLock.RLock()
+ for _, peer := range n.wsPeers {
+ peers = append(peers, Peer(peer))
+ }
+ n.wsPeersLock.RUnlock()
+
+ case PeersConnectedIn:
+ n.wsPeersLock.RLock()
+ for _, peer := range n.wsPeers {
+ if !peer.outgoing {
+ peers = append(peers, Peer(peer))
+ }
+ }
+ n.wsPeersLock.RUnlock()
+ }
}
- n.wsPeersLock.RUnlock()
return peers
}
@@ -468,6 +583,23 @@ func (n *P2PNetwork) wsStreamHandler(ctx context.Context, peer peer.ID, stream n
return
}
} else {
+ n.wsPeersLock.Lock()
+ numOutgoingPeers := 0
+ for _, peer := range n.wsPeers {
+ if peer.outgoing {
+ n.log.Debugf("outgoing peer orig=%s addr=%s", peer.OriginAddress(), peer.GetAddress())
+ numOutgoingPeers++
+ }
+ }
+ n.wsPeersLock.Unlock()
+ if numOutgoingPeers >= n.config.GossipFanout {
+ // this appears to be some auxiliary connection made by libp2p itself like DHT connection.
+ // skip this connection since there are already enough peers
+ n.log.Debugf("skipping outgoing connection to peer %s: num outgoing %d > fanout %d ", peer, numOutgoingPeers, n.config.GossipFanout)
+ stream.Close()
+ return
+ }
+
_, err := stream.Write([]byte("1"))
if err != nil {
n.log.Warnf("wsStreamHandler: error sending initial message: %s", err)
@@ -476,7 +608,8 @@ func (n *P2PNetwork) wsStreamHandler(ctx context.Context, peer peer.ID, stream n
}
// get address for peer ID
- addr := stream.Conn().RemoteMultiaddr().String()
+ ma := stream.Conn().RemoteMultiaddr()
+ addr := ma.String()
if addr == "" {
n.log.Warnf("Could not get address for peer %s", peer)
}
@@ -492,6 +625,30 @@ func (n *P2PNetwork) wsStreamHandler(ctx context.Context, peer peer.ID, stream n
n.wsPeersToIDs[wsp] = peer
n.wsPeersLock.Unlock()
n.wsPeersChangeCounter.Add(1)
+
+ event := "ConnectedOut"
+ msg := "Made outgoing connection to peer %s"
+ if incoming {
+ event = "ConnectedIn"
+ msg = "Accepted incoming connection from peer %s"
+ }
+ localAddr, _ := n.Address()
+ n.log.With("event", event).With("remote", addr).With("local", localAddr).Infof(msg, peer.String())
+
+ if n.log.GetLevel() >= logging.Debug {
+ n.log.Debugf("streams for %s conn %s ", stream.Conn().Stat().Direction.String(), stream.Conn().ID())
+ for _, s := range stream.Conn().GetStreams() {
+ n.log.Debugf("%s stream %s protocol %s", s.Stat().Direction.String(), s.ID(), s.Protocol())
+ }
+ }
+ // TODO: add telemetry
+ // n.log.EventWithDetails(telemetryspec.Network, telemetryspec.ConnectPeerEvent,
+ // telemetryspec.PeerEventDetails{
+ // Address: addr,
+ // TelemetryGUID: trackedRequest.otherTelemetryGUID,
+ // Incoming: true,
+ // InstanceName: trackedRequest.otherInstanceName,
+ // })
}
// peerRemoteClose called from wsPeer to report that it has closed
diff --git a/network/p2pNetwork_test.go b/network/p2pNetwork_test.go
index e4e811f695..5cabaf7a57 100644
--- a/network/p2pNetwork_test.go
+++ b/network/p2pNetwork_test.go
@@ -19,6 +19,8 @@ package network
import (
"context"
"fmt"
+ "io"
+ "net/http"
"sync"
"sync/atomic"
"testing"
@@ -27,6 +29,7 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network/p2p"
+ "github.com/algorand/go-algorand/network/p2p/dnsaddr"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
@@ -34,6 +37,7 @@ import (
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
peerstore "github.com/libp2p/go-libp2p/core/peer"
+ "github.com/multiformats/go-multiaddr"
ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)
@@ -49,7 +53,9 @@ func TestP2PSubmitTX(t *testing.T) {
defer netA.Stop()
peerInfoA := netA.service.AddrInfo()
+ fmt.Print("peerInfoA is ", peerInfoA)
addrsA, err := peerstore.AddrInfoToP2pAddrs(&peerInfoA)
+ fmt.Printf("addrsA is %v\n", addrsA)
require.NoError(t, err)
require.NotZero(t, addrsA[0])
@@ -225,9 +231,7 @@ func (s *mockService) DialPeersUntilTargetCount(targetConnCount int) {
}
func (s *mockService) ClosePeer(peer peer.ID) error {
- if _, ok := s.peers[peer]; ok {
- delete(s.peers, peer)
- }
+ delete(s.peers, peer)
return nil
}
@@ -246,10 +250,6 @@ func (s *mockService) Publish(ctx context.Context, topic string, data []byte) er
return nil
}
-func (s *mockService) setAddrs(addrs []ma.Multiaddr) {
- s.addrs = addrs
-}
-
func makeMockService(id peer.ID, addrs []ma.Multiaddr) *mockService {
return &mockService{
id: id,
@@ -317,6 +317,31 @@ func TestP2PNetworkAddress(t *testing.T) {
require.Empty(t, retAddr)
}
+type nilResolveController struct{}
+
+func (c *nilResolveController) Resolver() dnsaddr.Resolver {
+ return nil
+}
+
+func (c *nilResolveController) NextResolver() dnsaddr.Resolver {
+ return nil
+}
+
+type mockResolveController struct {
+ nilResolveController
+}
+
+func (c *mockResolveController) Resolver() dnsaddr.Resolver {
+ return &mockResolver{}
+}
+
+type mockResolver struct{}
+
+func (r *mockResolver) Resolve(ctx context.Context, maddr multiaddr.Multiaddr) ([]multiaddr.Multiaddr, error) {
+ ma, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")
+ return []multiaddr.Multiaddr{ma}, err
+}
+
func TestBootstrapFunc(t *testing.T) {
t.Parallel()
partitiontest.PartitionTest(t)
@@ -334,7 +359,8 @@ func TestBootstrapFunc(t *testing.T) {
b.cfg = config.GetDefaultLocal()
b.cfg.DNSBootstrapID = ".algodev.network"
b.cfg.DNSSecurityFlags = 0
- b.networkID = "test"
+ b.networkID = "devnet"
+ b.resolveControler = &mockResolveController{}
addrs := b.BootstrapFunc()
@@ -352,7 +378,8 @@ func TestGetBootstrapPeersFailure(t *testing.T) {
cfg.DNSSecurityFlags = 0
cfg.DNSBootstrapID = "non-existent.algodev.network"
- addrs := getBootstrapPeers(cfg, "test")
+ controller := nilResolveController{}
+ addrs := getBootstrapPeers(cfg, "test", &controller)
require.Equal(t, 0, len(addrs))
}
@@ -365,7 +392,8 @@ func TestGetBootstrapPeersInvalidAddr(t *testing.T) {
cfg.DNSSecurityFlags = 0
cfg.DNSBootstrapID = ".algodev.network"
- addrs := getBootstrapPeers(cfg, "testInvalidAddr")
+ controller := nilResolveController{}
+ addrs := getBootstrapPeers(cfg, "testInvalidAddr", &controller)
require.Equal(t, 0, len(addrs))
}
@@ -456,6 +484,7 @@ func TestP2PNetworkDHTCapabilities(t *testing.T) {
)
t.Logf("peers connected")
+ nets := []*P2PNetwork{netA, netB, netC}
discs := []*p2p.CapabilitiesDiscovery{netA.capabilitiesDiscovery, netB.capabilitiesDiscovery, netC.capabilitiesDiscovery}
var wg sync.WaitGroup
@@ -480,10 +509,12 @@ func TestP2PNetworkDHTCapabilities(t *testing.T) {
}
wg.Add(len(discs))
- for _, disc := range discs {
- go func(disc *p2p.CapabilitiesDiscovery) {
+ for i := range discs {
+ go func(idx int) {
+ disc := discs[idx]
defer wg.Done()
- if disc == netA.capabilitiesDiscovery {
+ // skip netA since it is special for the test cap=netA
+ if test.name == "cap=netA" && disc == netA.capabilitiesDiscovery {
return
}
require.Eventuallyf(t,
@@ -498,9 +529,100 @@ func TestP2PNetworkDHTCapabilities(t *testing.T) {
time.Second,
fmt.Sprintf("Not all expected %s cap peers were found", cap),
)
- }(disc)
+ // ensure GetPeers gets PeersPhonebookArchivalNodes peers
+ // it appears there are artifical peers because of listening on localhost and on a real network interface
+ // so filter out and save only unique peers by their IDs
+ net := nets[idx]
+ peers := net.GetPeers(PeersPhonebookArchivalNodes)
+ uniquePeerIDs := make(map[peer.ID]struct{})
+ for _, peer := range peers {
+ wsPeer := peer.(*wsPeerCore)
+ pi, err := peerstore.AddrInfoFromString(wsPeer.rootURL)
+ require.NoError(t, err)
+ uniquePeerIDs[pi.ID] = struct{}{}
+ }
+ require.Equal(t, test.numCapPeers, len(uniquePeerIDs))
+ }(i)
}
wg.Wait()
})
}
}
+
+// TestMultiaddrConversionToFrom ensures Multiaddr can be serialized back to an address without losing information
+func TestMultiaddrConversionToFrom(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ a := "/ip4/192.168.1.1/tcp/8180/p2p/Qmewz5ZHN1AAGTarRbMupNPbZRfg3p5jUGoJ3JYEatJVVk"
+ ma, err := multiaddr.NewMultiaddr(a)
+ require.NoError(t, err)
+ require.Equal(t, a, ma.String())
+
+ // this conversion drops the p2p proto part
+ pi, err := peer.AddrInfoFromP2pAddr(ma)
+ require.NoError(t, err)
+ require.NotEqual(t, a, pi.Addrs[0].String())
+ require.Len(t, pi.Addrs, 1)
+
+ mas, err := peer.AddrInfoToP2pAddrs(pi)
+ require.NoError(t, err)
+ require.Len(t, mas, 1)
+ require.Equal(t, a, mas[0].String())
+}
+
+type p2phttpHandler struct {
+ retData string
+}
+
+func (h *p2phttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte(h.retData))
+}
+
+func TestP2PHTTPHandler(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableDHTProviders = true
+ cfg.GossipFanout = 1
+ log := logging.TestingLog(t)
+
+ netA, err := NewP2PNetwork(log, cfg, "", nil, genesisID, config.Devtestnet, &nopeNodeInfo{})
+ require.NoError(t, err)
+
+ h := &p2phttpHandler{"hello"}
+ netA.RegisterHTTPHandler("/test", h)
+
+ h2 := &p2phttpHandler{"world"}
+ netA.RegisterHTTPHandler("/bar", h2)
+
+ netA.Start()
+ defer netA.Stop()
+
+ peerInfoA := netA.service.AddrInfo()
+ addrsA, err := peerstore.AddrInfoToP2pAddrs(&peerInfoA)
+ require.NoError(t, err)
+ require.NotZero(t, addrsA[0])
+
+ httpClient, err := p2p.MakeHTTPClient(p2p.AlgorandP2pHTTPProtocol, netA.service.AddrInfo())
+ require.NoError(t, err)
+ resp, err := httpClient.Get("/test")
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ body, err := io.ReadAll(resp.Body)
+ require.NoError(t, err)
+ require.Equal(t, "hello", string(body))
+
+ httpClient, err = p2p.MakeHTTPClient(p2p.AlgorandP2pHTTPProtocol, netA.service.AddrInfo())
+ require.NoError(t, err)
+ resp, err = httpClient.Get("/bar")
+ require.NoError(t, err)
+ defer resp.Body.Close()
+
+ body, err = io.ReadAll(resp.Body)
+ require.NoError(t, err)
+ require.Equal(t, "world", string(body))
+
+}
diff --git a/network/wsPeer.go b/network/wsPeer.go
index 6477285ade..06af7c6bad 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -348,6 +348,11 @@ type TCPInfoUnicastPeer interface {
// Create a wsPeerCore object
func makePeerCore(ctx context.Context, net GossipNode, log logging.Logger, readBuffer chan<- IncomingMessage, rootURL string, roundTripper http.RoundTripper, originAddress string) wsPeerCore {
+ return makePeerCoreWithClient(ctx, net, log, readBuffer, rootURL, http.Client{Transport: roundTripper}, originAddress)
+}
+
+// Create a wsPeerCore object
+func makePeerCoreWithClient(ctx context.Context, net GossipNode, log logging.Logger, readBuffer chan<- IncomingMessage, rootURL string, client http.Client, originAddress string) wsPeerCore {
return wsPeerCore{
net: net,
netCtx: ctx,
@@ -355,7 +360,7 @@ func makePeerCore(ctx context.Context, net GossipNode, log logging.Logger, readB
readBuffer: readBuffer,
rootURL: rootURL,
originAddress: originAddress,
- client: http.Client{Transport: roundTripper},
+ client: client,
}
}
diff --git a/node/node_test.go b/node/node_test.go
index dabb7958a5..f82df98b84 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -33,13 +33,13 @@ import (
"github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
- "github.com/algorand/go-algorand/data"
"github.com/algorand/go-algorand/data/account"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
+ "github.com/algorand/go-algorand/network/p2p"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/stateproof"
"github.com/algorand/go-algorand/test/partitiontest"
@@ -61,31 +61,78 @@ var defaultConfig = config.Local{
IncomingConnectionsLimit: -1,
}
+type nodeInfo struct {
+ idx int
+ host string
+ wsPort int
+ p2pPort int
+ p2pID p2p.PeerID
+ rootDir string
+ genesis bookkeeping.Genesis
+}
+
+func (ni nodeInfo) wsNetAddr() string {
+ return fmt.Sprintf("%s:%d", ni.host, ni.wsPort)
+}
+
+func (ni nodeInfo) p2pNetAddr() string {
+ return fmt.Sprintf("%s:%d", ni.host, ni.p2pPort)
+}
+
+func (ni nodeInfo) p2pMultiAddr() string {
+ return fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", ni.host, ni.p2pPort, ni.p2pID.String())
+}
+
+type configHook func(ni nodeInfo, cfg config.Local) (nodeInfo, config.Local)
+type phonebookHook func([]nodeInfo, int) []string
+
func setupFullNodes(t *testing.T, proto protocol.ConsensusVersion, verificationPool execpool.BacklogPool, customConsensus config.ConsensusProtocols) ([]*AlgorandFullNode, []string) {
+ minMoneyAtStart := 10000
+ maxMoneyAtStart := 100000
+ gen := rand.New(rand.NewSource(2))
+
+ const numAccounts = 10
+ acctStake := make([]basics.MicroAlgos, numAccounts)
+ for i := range acctStake {
+ acctStake[i] = basics.MicroAlgos{Raw: uint64(minMoneyAtStart + (gen.Int() % (maxMoneyAtStart - minMoneyAtStart)))}
+ }
+
+ configHook := func(ni nodeInfo, cfg config.Local) (nodeInfo, config.Local) {
+ cfg.NetAddress = ni.wsNetAddr()
+ return ni, cfg
+ }
+
+ phonebookHook := func(nodes []nodeInfo, nodeIdx int) []string {
+ phonebook := make([]string, 0, len(nodes)-1)
+ for i := range nodes {
+ if i != nodeIdx {
+ phonebook = append(phonebook, nodes[i].wsNetAddr())
+ }
+ }
+ return phonebook
+ }
+ nodes, wallets := setupFullNodesEx(t, proto, verificationPool, customConsensus, acctStake, configHook, phonebookHook)
+ require.Len(t, nodes, numAccounts)
+ require.Len(t, wallets, numAccounts)
+ return nodes, wallets
+}
+
+func setupFullNodesEx(
+ t *testing.T, proto protocol.ConsensusVersion, verificationPool execpool.BacklogPool, customConsensus config.ConsensusProtocols,
+ acctStake []basics.MicroAlgos, configHook configHook, phonebookHook phonebookHook,
+) ([]*AlgorandFullNode, []string) {
+
util.SetFdSoftLimit(1000)
+
f, _ := os.Create(t.Name() + ".log")
logging.Base().SetJSONFormatter()
logging.Base().SetOutput(f)
logging.Base().SetLevel(logging.Debug)
-
- numAccounts := 10
- minMoneyAtStart := 10000
- maxMoneyAtStart := 100000
+ t.Logf("Logging to %s\n", t.Name()+".log")
firstRound := basics.Round(0)
lastRound := basics.Round(200)
- genesis := make(map[basics.Address]basics.AccountData)
- gen := rand.New(rand.NewSource(2))
- neighbors := make([]string, numAccounts)
- for i := range neighbors {
- neighbors[i] = "127.0.0.1:" + strconv.Itoa(10000+i)
- }
-
- wallets := make([]string, numAccounts)
- nodes := make([]*AlgorandFullNode, numAccounts)
- rootDirs := make([]string, 0)
-
// The genesis configuration is missing allocations, but that's OK
// because we explicitly generated the sqlite database above (in
// installFullNode).
@@ -97,16 +144,31 @@ func setupFullNodes(t *testing.T, proto protocol.ConsensusVersion, verificationP
RewardsPool: poolAddr.String(),
}
+ genesis := make(map[basics.Address]basics.AccountData)
+ numAccounts := len(acctStake)
+ wallets := make([]string, numAccounts)
+ nodeInfos := make([]nodeInfo, numAccounts)
+
for i := range wallets {
rootDirectory := t.TempDir()
- rootDirs = append(rootDirs, rootDirectory)
+ nodeInfos[i] = nodeInfo{
+ idx: i,
+ host: "127.0.0.1",
+ wsPort: 10000 + 100*i,
+ p2pPort: 10000 + 100*i + 1,
+ rootDir: rootDirectory,
+ genesis: g,
+ }
- defaultConfig.NetAddress = neighbors[i]
- defaultConfig.SaveToDisk(rootDirectory)
+ ni, cfg := configHook(nodeInfos[i], defaultConfig)
+ nodeInfos[i] = ni
+ cfg.SaveToDisk(rootDirectory)
- // Save empty phonebook - we'll add peers after they've been assigned listening ports
- err := config.SavePhonebookToDisk(make([]string, 0), rootDirectory)
- require.NoError(t, err)
+ t.Logf("Root directory of node %d (%s): %s\n", i, ni.wsNetAddr(), rootDirectory)
+
+ // // Save empty phonebook - we'll add peers after they've been assigned listening ports
+ // err := config.SavePhonebookToDisk(make([]string, 0), rootDirectory)
+ // require.NoError(t, err)
genesisDir := filepath.Join(rootDirectory, g.ID())
os.Mkdir(genesisDir, 0700)
@@ -140,7 +202,7 @@ func setupFullNodes(t *testing.T, proto protocol.ConsensusVersion, verificationP
data := basics.AccountData{
Status: basics.Online,
- MicroAlgos: basics.MicroAlgos{Raw: uint64(minMoneyAtStart + (gen.Int() % (maxMoneyAtStart - minMoneyAtStart)))},
+ MicroAlgos: acctStake[i],
SelectionID: part.VRFSecrets().PK,
VoteID: part.VotingSecrets().OneTimeSignatureVerifier,
}
@@ -152,34 +214,37 @@ func setupFullNodes(t *testing.T, proto protocol.ConsensusVersion, verificationP
MicroAlgos: basics.MicroAlgos{Raw: uint64(100000)},
}
- bootstrap := bookkeeping.MakeGenesisBalances(genesis, sinkAddr, poolAddr)
+ for addr, data := range genesis {
+ g.Allocation = append(g.Allocation, bookkeeping.GenesisAllocation{
+ Address: addr.String(),
+ State: bookkeeping.GenesisAccountData{
+ Status: data.Status,
+ MicroAlgos: data.MicroAlgos,
+ VoteID: data.VoteID,
+ StateProofID: data.StateProofID,
+ SelectionID: data.SelectionID,
+ VoteFirstValid: data.VoteFirstValid,
+ VoteLastValid: data.VoteLastValid,
+ VoteKeyDilution: data.VoteKeyDilution,
+ },
+ })
+ }
- for i, rootDirectory := range rootDirs {
+ nodes := make([]*AlgorandFullNode, numAccounts)
+ for i := range nodes {
+ rootDirectory := nodeInfos[i].rootDir
genesisDir := filepath.Join(rootDirectory, g.ID())
- ledgerFilenamePrefix := filepath.Join(genesisDir, config.LedgerFilenamePrefix)
if customConsensus != nil {
- err := config.SaveConfigurableConsensus(genesisDir, customConsensus)
- require.Nil(t, err)
+ err0 := config.SaveConfigurableConsensus(genesisDir, customConsensus)
+ require.Nil(t, err0)
+ err0 = config.LoadConfigurableConsensusProtocols(genesisDir)
+ require.Nil(t, err0)
}
- err1 := config.LoadConfigurableConsensusProtocols(genesisDir)
- require.Nil(t, err1)
- nodeID := fmt.Sprintf("Node%d", i)
- const inMem = false
- cfg, err := config.LoadConfigFromDisk(rootDirectory)
- require.NoError(t, err)
- cfg.Archival = true
- _, err = data.LoadLedger(logging.Base().With("name", nodeID), ledgerFilenamePrefix, inMem, g.Proto, bootstrap, g.ID(), g.Hash(), nil, cfg)
- require.NoError(t, err)
- }
- for i := range nodes {
- var nodeNeighbors []string
- nodeNeighbors = append(nodeNeighbors, neighbors[:i]...)
- nodeNeighbors = append(nodeNeighbors, neighbors[i+1:]...)
- rootDirectory := rootDirs[i]
cfg, err := config.LoadConfigFromDisk(rootDirectory)
+ phonebook := phonebookHook(nodeInfos, i)
require.NoError(t, err)
- node, err := MakeFull(logging.Base().With("source", t.Name()+strconv.Itoa(i)), rootDirectory, cfg, nodeNeighbors, g)
+ node, err := MakeFull(logging.Base(), rootDirectory, cfg, phonebook, g)
nodes[i] = node
require.NoError(t, err)
}
@@ -190,7 +255,14 @@ func setupFullNodes(t *testing.T, proto protocol.ConsensusVersion, verificationP
func TestSyncingFullNode(t *testing.T) {
partitiontest.PartitionTest(t)
- t.Skip("Flaky in nightly test environment")
+ if testing.Short() {
+ t.Skip("Test takes ~50 seconds.")
+ }
+
+ if (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" && runtime.GOOS != "darwin") &&
+ strings.ToUpper(os.Getenv("CIRCLECI")) == "TRUE" {
+ t.Skip("Test is too heavy for amd64 builder running in parallel with other packages")
+ }
backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
defer backlogPool.Shutdown()
@@ -203,7 +275,7 @@ func TestSyncingFullNode(t *testing.T) {
initialRound := nodes[0].ledger.NextRound()
- startAndConnectNodes(nodes, true)
+ startAndConnectNodes(nodes, defaultFirstNodeStartDelay)
counter := 0
for tests := uint64(0); tests < 16; tests++ {
@@ -252,7 +324,7 @@ func TestInitialSync(t *testing.T) {
t.Skip("Test takes ~25 seconds.")
}
- if (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") &&
+ if (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" && runtime.GOOS != "darwin") &&
strings.ToUpper(os.Getenv("CIRCLECI")) == "TRUE" {
t.Skip("Test is too heavy for amd64 builder running in parallel with other packages")
}
@@ -267,7 +339,7 @@ func TestInitialSync(t *testing.T) {
}
initialRound := nodes[0].ledger.NextRound()
- startAndConnectNodes(nodes, true)
+ startAndConnectNodes(nodes, defaultFirstNodeStartDelay)
select {
case <-nodes[0].ledger.Wait(initialRound):
@@ -289,7 +361,14 @@ func TestInitialSync(t *testing.T) {
func TestSimpleUpgrade(t *testing.T) {
partitiontest.PartitionTest(t)
- t.Skip("Flaky in nightly test environment.")
+ if testing.Short() {
+ t.Skip("Test takes ~50 seconds.")
+ }
+
+ if (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" && runtime.GOOS != "darwin") &&
+ strings.ToUpper(os.Getenv("CIRCLECI")) == "TRUE" {
+ t.Skip("Test is too heavy for amd64 builder running in parallel with other packages")
+ }
backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
defer backlogPool.Shutdown()
@@ -338,13 +417,13 @@ func TestSimpleUpgrade(t *testing.T) {
initialRound := nodes[0].ledger.NextRound()
- startAndConnectNodes(nodes, false)
+ startAndConnectNodes(nodes, nodelayFirstNodeStartDelay)
maxRounds := basics.Round(16)
roundsCheckedForUpgrade := 0
for tests := basics.Round(0); tests < maxRounds; tests++ {
- blocks := make([]bookkeeping.Block, len(wallets), len(wallets))
+ blocks := make([]bookkeeping.Block, len(wallets))
for i := range wallets {
select {
case <-nodes[i].ledger.Wait(initialRound + tests):
@@ -387,10 +466,13 @@ func TestSimpleUpgrade(t *testing.T) {
require.Equal(t, 2, roundsCheckedForUpgrade)
}
-func startAndConnectNodes(nodes []*AlgorandFullNode, delayStartFirstNode bool) {
+const defaultFirstNodeStartDelay = 20 * time.Second
+const nodelayFirstNodeStartDelay = 0
+
+func startAndConnectNodes(nodes []*AlgorandFullNode, delayStartFirstNode time.Duration) {
var wg sync.WaitGroup
for i := range nodes {
- if delayStartFirstNode && i == 0 {
+ if delayStartFirstNode != nodelayFirstNodeStartDelay && i == 0 {
continue
}
wg.Add(1)
@@ -401,9 +483,9 @@ func startAndConnectNodes(nodes []*AlgorandFullNode, delayStartFirstNode bool) {
}
wg.Wait()
- if delayStartFirstNode {
+ if delayStartFirstNode != nodelayFirstNodeStartDelay {
connectPeers(nodes[1:])
- delayStartNode(nodes[0], nodes[1:], 20*time.Second)
+ delayStartNode(nodes[0], nodes[1:], delayStartFirstNode)
} else {
connectPeers(nodes)
}
@@ -754,3 +836,119 @@ func TestMaxSizesCorrect(t *testing.T) {
tsSize := uint64(network.MaxMessageLength)
require.Equal(t, tsSize, protocol.TopicMsgRespTag.MaxMessageSize())
}
+
+// TestNodeHybridTopology set ups 3 nodes network with the following topology:
+// N -- R -- A and ensures N can discover A and download blocks from it.
+//
+// N is a non-part node that joins the network later
+// R is a non-arhival relay node with block service disabled. It MUST NOT service blocks to force N to discover A.
+// A is a archival node that can only provide blocks.
+// Nodes N and A have only R in their initial phonebook, and all nodes are in hybrid mode.
+func TestNodeHybridTopology(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ const consensusTest0 = protocol.ConsensusVersion("test0")
+
+ configurableConsensus := make(config.ConsensusProtocols)
+
+ testParams0 := config.Consensus[protocol.ConsensusCurrentVersion]
+ testParams0.AgreementFilterTimeoutPeriod0 = 500 * time.Millisecond
+ configurableConsensus[consensusTest0] = testParams0
+
+ minMoneyAtStart := 1_000_000
+ maxMoneyAtStart := 100_000_000_000
+ gen := rand.New(rand.NewSource(2))
+
+ const numAccounts = 3
+ acctStake := make([]basics.MicroAlgos, numAccounts)
+ for i := range acctStake {
+ acctStake[i] = basics.MicroAlgos{Raw: uint64(minMoneyAtStart + (gen.Int() % (maxMoneyAtStart - minMoneyAtStart)))}
+ }
+ acctStake[0] = basics.MicroAlgos{} // no stake at node 0
+
+ configHook := func(ni nodeInfo, cfg config.Local) (nodeInfo, config.Local) {
+ cfg = config.GetDefaultLocal()
+ if ni.idx != 2 {
+ cfg.EnableBlockService = false
+ cfg.EnableGossipBlockService = false
+ cfg.EnableLedgerService = false
+ cfg.CatchpointInterval = 0
+ cfg.Archival = false
+ } else {
+ // node 2 is archival
+ cfg.EnableBlockService = true
+ cfg.EnableGossipBlockService = true
+ cfg.EnableLedgerService = true
+ cfg.CatchpointInterval = 200
+ cfg.Archival = true
+ }
+ if ni.idx == 0 {
+ // do not allow node 0 (N) to make any outgoing connections
+ cfg.GossipFanout = 0
+ }
+
+ cfg.NetAddress = ni.wsNetAddr()
+ cfg.EnableP2PHybridMode = true
+ cfg.EnableDHTProviders = true
+ cfg.P2PPersistPeerID = true
+ genesisDirs, err := cfg.EnsureAndResolveGenesisDirs(ni.rootDir, ni.genesis.ID(), nil)
+ require.NoError(t, err)
+ privKey, err := p2p.GetPrivKey(cfg, genesisDirs.RootGenesisDir)
+ require.NoError(t, err)
+ ni.p2pID, err = p2p.PeerIDFromPublicKey(privKey.GetPublic())
+ require.NoError(t, err)
+
+ cfg.P2PListenAddress = ni.p2pNetAddr()
+ return ni, cfg
+ }
+
+ phonebookHook := func(ni []nodeInfo, i int) []string {
+ switch i {
+ case 0:
+ // node 0 (N) only accept connections to work around the peer selector
+ // ConnectedOut priority. TODO: merge switching to archival peers from master
+ // when ready.
+ t.Logf("Node%d phonebook: empty", i)
+ return []string{}
+ case 1:
+ // node 1 (R) connectes to all
+ t.Logf("Node%d phonebook: %s, %s, %s, %s", i, ni[0].wsNetAddr(), ni[2].wsNetAddr(), ni[0].p2pMultiAddr(), ni[2].p2pMultiAddr())
+ return []string{ni[0].wsNetAddr(), ni[2].wsNetAddr(), ni[0].p2pMultiAddr(), ni[2].p2pMultiAddr()}
+ case 2:
+ // node 2 (A) connects to R
+ t.Logf("Node%d phonebook: %s, %s", i, ni[1].wsNetAddr(), ni[1].p2pMultiAddr())
+ return []string{ni[1].wsNetAddr(), ni[1].p2pMultiAddr()}
+ default:
+ t.Errorf("not expected number of nodes: %d", i)
+ t.FailNow()
+ }
+ return nil
+ }
+
+ backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
+ defer backlogPool.Shutdown()
+
+ nodes, wallets := setupFullNodesEx(t, consensusTest0, backlogPool, configurableConsensus, acctStake, configHook, phonebookHook)
+ require.Len(t, nodes, 3)
+ require.Len(t, wallets, 3)
+ for i := 0; i < len(nodes); i++ {
+ defer os.Remove(wallets[i])
+ defer nodes[i].Stop()
+ }
+
+ startAndConnectNodes(nodes, 10*time.Second)
+
+ initialRound := nodes[0].ledger.NextRound()
+ targetRound := initialRound + 10
+
+ select {
+ case <-nodes[0].ledger.Wait(targetRound):
+ e0, err := nodes[0].ledger.Block(targetRound)
+ require.NoError(t, err)
+ e1, err := nodes[1].ledger.Block(targetRound)
+ require.NoError(t, err)
+ require.Equal(t, e1.Hash(), e0.Hash())
+ case <-time.After(120 * time.Second):
+ require.Fail(t, fmt.Sprintf("no block notification for wallet: %v.", wallets[0]))
+ }
+}
diff --git a/tools/block-generator/go.mod b/tools/block-generator/go.mod
index 435e1ccf69..ae047a3fb1 100644
--- a/tools/block-generator/go.mod
+++ b/tools/block-generator/go.mod
@@ -51,19 +51,18 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gopacket v1.1.19 // indirect
- github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect
+ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
- github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect
- github.com/huin/goupnp v1.2.0 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/boxo v0.10.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
@@ -76,7 +75,7 @@ require (
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/jmespath/go-jmespath v0.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
@@ -84,23 +83,23 @@ require (
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
- github.com/libp2p/go-libp2p v0.29.1 // indirect
+ github.com/libp2p/go-libp2p v0.32.2 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.24.3 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
- github.com/libp2p/go-libp2p-pubsub v0.9.3 // indirect
+ github.com/libp2p/go-libp2p-pubsub v0.10.0 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
- github.com/libp2p/go-reuseport v0.3.0 // indirect
+ github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
- github.com/miekg/dns v1.1.55 // indirect
+ github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -108,17 +107,17 @@ require (
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
- github.com/multiformats/go-multiaddr v0.10.1 // indirect
+ github.com/multiformats/go-multiaddr v0.12.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
- github.com/multiformats/go-multistream v0.4.1 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olivere/elastic v6.2.14+incompatible // indirect
- github.com/onsi/ginkgo/v2 v2.11.0 // indirect
- github.com/opencontainers/runtime-spec v1.0.2 // indirect
+ github.com/onsi/ginkgo/v2 v2.13.0 // indirect
+ github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
@@ -130,10 +129,9 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
- github.com/quic-go/qtls-go1-19 v0.3.3 // indirect
- github.com/quic-go/qtls-go1-20 v0.2.3 // indirect
- github.com/quic-go/quic-go v0.36.3 // indirect
- github.com/quic-go/webtransport-go v0.5.3 // indirect
+ github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
+ github.com/quic-go/quic-go v0.39.4 // indirect
+ github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
@@ -144,19 +142,19 @@ require (
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
- go.uber.org/atomic v1.11.0 // indirect
- go.uber.org/dig v1.17.0 // indirect
- go.uber.org/fx v1.20.0 // indirect
+ go.uber.org/dig v1.17.1 // indirect
+ go.uber.org/fx v1.20.1 // indirect
+ go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.24.0 // indirect
+ go.uber.org/zap v1.26.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
- golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
- golang.org/x/mod v0.12.0 // indirect
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
+ golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
- golang.org/x/tools v0.11.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 // indirect
diff --git a/tools/block-generator/go.sum b/tools/block-generator/go.sum
index 80fcb7825c..037443f8ed 100644
--- a/tools/block-generator/go.sum
+++ b/tools/block-generator/go.sum
@@ -169,8 +169,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -205,8 +203,8 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA=
-github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b h1:RMpPgZTSApbPf7xaVel+QkoGPRLFLrwFO89uDUHEGf0=
+github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -231,12 +229,12 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU=
-github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
+github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
-github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -291,8 +289,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
-github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
+github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -318,16 +316,16 @@ 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.29.1 h1:yNeg6XgP8gbdc4YSrwiIt5T1TGOrVjH8dzl8h0GIOfQ=
-github.com/libp2p/go-libp2p v0.29.1/go.mod h1:20El+LLy3/YhdUYIvGbLnvVJN32nMdqY6KXBENRAfLY=
+github.com/libp2p/go-libp2p v0.32.2 h1:s8GYN4YJzgUoyeYNPdW7JZeZ5Ee31iNaIBfGYMAY4FQ=
+github.com/libp2p/go-libp2p v0.32.2/go.mod h1:E0LKe+diV/ZVJVnOJby8VC5xzHF0660osg71skcxJvk=
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.24.3 h1:VjxtDVWaaf4UFjGBf+yl2JCiGaHx7+ctAUa9oJCR3QE=
github.com/libp2p/go-libp2p-kad-dht v0.24.3/go.mod h1:BShPzRbK6+fN3hk8a0WGAYKpb8m4k+DtchkqouGTrSg=
github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
-github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo=
-github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc=
+github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA=
+github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
@@ -337,8 +335,8 @@ github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
-github.com/libp2p/go-reuseport v0.3.0 h1:iiZslO5byUYZEg9iCwJGf5h+sf1Agmqx2V2FDjPyvUw=
-github.com/libp2p/go-reuseport v0.3.0/go.mod h1:laea40AimhtfEqysZ71UpYj4S+R9VpH8PgqLo7L+SwI=
+github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
+github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
@@ -353,8 +351,8 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
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=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
@@ -366,8 +364,8 @@ github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQ
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
+github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
@@ -395,8 +393,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
-github.com/multiformats/go-multiaddr v0.10.1 h1:HghtFrWyZEPrpTvgAMFJi6gFdgHfs2cb0pyfDsk+lqU=
-github.com/multiformats/go-multiaddr v0.10.1/go.mod h1:jLEZsA61rwWNZQTHHnqq2HNa+4os/Hz54eqiRnsRqYQ=
+github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE=
+github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8=
github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
@@ -408,8 +406,8 @@ github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI1
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
-github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo=
-github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
@@ -424,13 +422,14 @@ github.com/olivere/elastic v6.2.14+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGe
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
-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/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
+github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
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/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
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=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
@@ -464,14 +463,12 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
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-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE=
-github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
-github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI=
-github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
-github.com/quic-go/quic-go v0.36.3 h1:f+yOqeGhMoRX7/M3wmEw/djhzKWr15FtQysox85/834=
-github.com/quic-go/quic-go v0.36.3/go.mod h1:qxQumdeKw5GmWs1OsTZZnOxzSI+RJWuhf1O8FN35L2o=
-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/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
+github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
+github.com/quic-go/quic-go v0.39.4 h1:PelfiuG7wXEffUT2yceiqz5V6Pc0TA5ruOd1LcmFc1s=
+github.com/quic-go/quic-go v0.39.4/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
+github.com/quic-go/webtransport-go v0.6.0 h1:CvNsKqc4W2HljHJnoT+rMmbRJybShZ0YPFDD3NxaZLY=
+github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1abRaosM2yGOyiikEc=
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -585,13 +582,14 @@ go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLk
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
-go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI=
-go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU=
-go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ=
-go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0=
+go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
+go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
+go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -599,8 +597,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -618,8 +616,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
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=
@@ -632,8 +630,8 @@ 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/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -673,8 +671,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
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/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -736,11 +734,10 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
-golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
-golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
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=