diff --git a/.github/actions/go-test-setup/action.yml b/.github/actions/go-test-setup/action.yml index 1836ae8dc..b85c81334 100644 --- a/.github/actions/go-test-setup/action.yml +++ b/.github/actions/go-test-setup/action.yml @@ -9,10 +9,10 @@ runs: shell: bash # This matches only tests with "NoCover" in their test name to avoid running all tests again. run: go test -tags nocover -run NoCover -v ./... - - name: Run synctests tests. These are tests that require go 1.24 and the experimental testing/synctest package + - name: Run synctests tests. These are tests that require go 1.25 and the experimental testing/synctest package shell: bash - if: ${{ contains(matrix.go, '1.24') }} - run: go test -tags goexperiment.synctest -run "_synctest$" -v ./... + if: ${{ contains(matrix.go, '1.25') }} + run: go test -run "_synctest$" -v ./... - name: Install testing tools shell: bash run: cd scripts/test_analysis && go install ./cmd/gotest2sql diff --git a/FUNDING.json b/FUNDING.json index 5952e90cb..5b8b1bf46 100644 --- a/FUNDING.json +++ b/FUNDING.json @@ -4,7 +4,7 @@ }, "drips": { "filecoin": { - "ownedBy": "0x53DCAf729e11022D5b8949946f6601211C662B38" + "ownedBy": "0xEF22379b7527762a00FC5820AF55BdE363624f03" } } } diff --git a/core/peer/peer.go b/core/peer/peer.go index b77fb684e..ddea302e6 100644 --- a/core/peer/peer.go +++ b/core/peer/peer.go @@ -169,7 +169,10 @@ func IDFromPublicKey(pk ic.PubKey) (ID, error) { if AdvancedEnableInlining && len(b) <= maxInlineKeyLength { alg = mh.IDENTITY } - hash, _ := mh.Sum(b, alg, -1) + hash, err := mh.Sum(b, alg, -1) + if err != nil { + return "", err + } return ID(hash), nil } diff --git a/go.mod b/go.mod index a373b025c..ca7d94d67 100644 --- a/go.mod +++ b/go.mod @@ -19,18 +19,17 @@ require ( github.com/ipfs/go-datastore v0.8.2 github.com/jackpal/go-nat-pmp v1.0.2 github.com/jbenet/go-temp-err-catcher v0.1.0 - github.com/klauspost/compress v1.18.0 github.com/koron/go-ssdp v0.0.6 github.com/libp2p/go-buffer-pool v0.1.0 github.com/libp2p/go-flow-metrics v0.2.0 github.com/libp2p/go-libp2p-asn-util v0.4.1 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-msgio v0.3.0 - github.com/libp2p/go-netroute v0.3.0 + github.com/libp2p/go-netroute v0.4.0 github.com/libp2p/go-reuseport v0.4.0 github.com/libp2p/go-yamux/v5 v5.0.1 github.com/libp2p/zeroconf/v2 v2.2.0 - github.com/marcopolo/simnet v0.0.1 + github.com/marcopolo/simnet v0.0.4 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b github.com/mr-tron/base58 v1.2.0 @@ -52,9 +51,9 @@ require ( github.com/pion/webrtc/v4 v4.1.2 github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_model v0.6.2 - github.com/quic-go/quic-go v0.55.0 - github.com/quic-go/webtransport-go v0.9.0 - github.com/stretchr/testify v1.10.0 + github.com/quic-go/quic-go v0.59.0 + github.com/quic-go/webtransport-go v0.10.0 + github.com/stretchr/testify v1.11.1 go.uber.org/fx v1.24.0 go.uber.org/goleak v1.3.0 go.uber.org/mock v0.5.2 @@ -70,7 +69,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/miekg/dns v1.1.66 // indirect @@ -94,7 +93,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common v0.64.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect - github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/wlynxg/anet v0.0.5 // indirect go.uber.org/dig v1.19.0 // indirect diff --git a/go.sum b/go.sum index 1ba6e1322..f7790f8fc 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,9 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,40 +13,16 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -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/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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hashicorp/golang-lru/arc/v2 v2.0.7 h1:QxkVTxwColcduO+LP7eJO56r2hFiG8zEbfAAzRv52KQ= github.com/hashicorp/golang-lru/arc/v2 v2.0.7/go.mod h1:Pe7gBlGdc8clY5LJ0LpJXMt5AmgmWNH1g+oFFVUHOEc= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -79,22 +39,14 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -108,22 +60,18 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= -github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q= +github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= 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/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv53Q= github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marcopolo/simnet v0.0.1 h1:rSMslhPz6q9IvJeFWDoMGxMIrlsbXau3NkuIXHGJxfg= -github.com/marcopolo/simnet v0.0.1/go.mod h1:WDaQkgLAjqDUEBAOXz22+1j6wXKfGlC5sD5XWt3ddOs= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= @@ -137,8 +85,6 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8Rv github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -166,9 +112,6 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= @@ -213,75 +156,39 @@ github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= -github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= -github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70= -github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= @@ -294,11 +201,7 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -308,24 +211,12 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4= golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -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= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= -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= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -339,26 +230,13 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -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= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -383,7 +261,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -393,53 +270,22 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/gologshim/gologshim.go b/gologshim/gologshim.go index f41800eaf..57ed3e8aa 100644 --- a/gologshim/gologshim.go +++ b/gologshim/gologshim.go @@ -1,11 +1,57 @@ +// Package gologshim provides slog-based logging for go-libp2p that works +// standalone or integrates with go-log for unified log management across +// IPFS/libp2p applications, without adding go-log as a dependency. +// +// # Usage +// +// Create loggers using the Logger function: +// +// var log = gologshim.Logger("subsystem") +// log.Debug("message", "key", "value") +// +// # Integration with go-log +// +// Applications can optionally connect go-libp2p to go-log by calling SetDefaultHandler: +// +// import golog "github.com/ipfs/go-log/v2" +// +// func init() { +// gologshim.SetDefaultHandler(golog.SlogHandler()) +// } +// +// When integrated, go-libp2p logs use go-log's formatting and can be controlled +// programmatically via go-log's SetLogLevel("subsystem", "level") API to adjust +// log verbosity per subsystem at runtime without restarting. +// +// Note: SlogHandler() works even when GOLOG_CAPTURE_DEFAULT_SLOG=false, making +// it more reliable than using slog.Default().Handler(). +// +// # Standalone Usage +// +// Without calling SetDefaultHandler, gologshim creates standalone slog handlers +// writing to stderr. This mode is useful when go-log is not present or when you +// want independent log configuration via backward-compatible (go-log) environment variables: +// +// - GOLOG_LOG_LEVEL: Set log levels per subsystem (e.g., "error,ping=debug") +// - GOLOG_LOG_FORMAT/GOLOG_LOG_FMT: Output format ("json" or text) +// - GOLOG_LOG_ADD_SOURCE: Include source location (default: true) +// - GOLOG_LOG_LABELS: Add key=value labels to all logs +// +// For integration details, see: https://github.com/ipfs/go-log/blob/master/README.md#slog-integration +// +// Note: This package exists as an intermediate solution while go-log uses zap +// internally. If go-log migrates from zap to native slog, this bridge layer +// could be simplified or removed entirely. package gologshim import ( + "context" "fmt" "log/slog" "os" "strings" "sync" + "sync/atomic" ) var lvlToLower = map[slog.Level]slog.Value{ @@ -15,26 +61,52 @@ var lvlToLower = map[slog.Level]slog.Value{ slog.LevelError: slog.StringValue("error"), } -// Logger returns a *slog.Logger with a logging level defined by the -// GOLOG_LOG_LEVEL env var. Supports different levels for different systems. e.g. -// GOLOG_LOG_LEVEL=foo=info,bar=debug,warn -// sets the foo system at level info, the bar system at level debug and the -// fallback level to warn. -// -// Prefer a parameterized logger over a global logger. -func Logger(system string) *slog.Logger { - var h slog.Handler - c := ConfigFromEnv() - handlerOpts := &slog.HandlerOptions{ - Level: c.LevelForSystem(system), - AddSource: c.addSource, +var defaultHandler atomic.Pointer[slog.Handler] + +// SetDefaultHandler allows an application to change the underlying handler used +// by gologshim as long as it's changed *before* the first log by the logger. +func SetDefaultHandler(handler slog.Handler) { + defaultHandler.Store(&handler) +} + +// dynamicHandler delays bridge detection until first log call to handle init order issues +type dynamicHandler struct { + system string + config *Config + once sync.Once + handler slog.Handler +} + +func (h *dynamicHandler) ensureHandler() slog.Handler { + h.once.Do(func() { + if hPtr := defaultHandler.Load(); hPtr != nil { + h.handler = *hPtr + } else { + h.handler = h.createFallbackHandler() + } + attrs := make([]slog.Attr, 0, 1+len(h.config.labels)) + // Use "logger" attribute for compatibility with go-log's Zap-based format + // and existing IPFS/libp2p tooling and dashboards. + attrs = append(attrs, slog.String("logger", h.system)) + attrs = append(attrs, h.config.labels...) + h.handler = h.handler.WithAttrs(attrs) + }) + + return h.handler +} + +func (h *dynamicHandler) createFallbackHandler() slog.Handler { + opts := &slog.HandlerOptions{ + Level: h.config.LevelForSystem(h.system), + AddSource: h.config.addSource, ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { - if a.Key == slog.TimeKey { + switch a.Key { + case slog.TimeKey: // ipfs go-log uses "ts" for time a.Key = "ts" - } else if a.Key == slog.LevelKey { - // ipfs go-log uses lowercase level names + case slog.LevelKey: if lvl, ok := a.Value.Any().(slog.Level); ok { + // ipfs go-log uses lowercase level names if s, ok := lvlToLower[lvl]; ok { a.Value = s } @@ -43,16 +115,40 @@ func Logger(system string) *slog.Logger { return a }, } - if c.format == logFormatText { - h = slog.NewTextHandler(os.Stderr, handlerOpts) - } else { - h = slog.NewJSONHandler(os.Stderr, handlerOpts) + if h.config.format == logFormatText { + return slog.NewTextHandler(os.Stderr, opts) } - attrs := make([]slog.Attr, 1+len(c.labels)) - attrs = append(attrs, slog.String("logger", system)) - attrs = append(attrs, c.labels...) - h = h.WithAttrs(attrs) - return slog.New(h) + + return slog.NewJSONHandler(os.Stderr, opts) +} + +func (h *dynamicHandler) Enabled(ctx context.Context, lvl slog.Level) bool { + return h.ensureHandler().Enabled(ctx, lvl) +} + +func (h *dynamicHandler) Handle(ctx context.Context, r slog.Record) error { + return h.ensureHandler().Handle(ctx, r) +} + +func (h *dynamicHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return h.ensureHandler().WithAttrs(attrs) +} + +func (h *dynamicHandler) WithGroup(name string) slog.Handler { + return h.ensureHandler().WithGroup(name) +} + +// Logger returns a *slog.Logger with a logging level defined by the +// GOLOG_LOG_LEVEL env var. Supports different levels for different systems. e.g. +// GOLOG_LOG_LEVEL=foo=info,bar=debug,warn +// sets the foo system at level info, the bar system at level debug and the +// fallback level to warn. +func Logger(system string) *slog.Logger { + c := ConfigFromEnv() + return slog.New(&dynamicHandler{ + system: system, + config: c, + }) } type logFormat = int diff --git a/gologshim/gologshim_test.go b/gologshim/gologshim_test.go new file mode 100644 index 000000000..dec64bfe6 --- /dev/null +++ b/gologshim/gologshim_test.go @@ -0,0 +1,247 @@ +package gologshim + +import ( + "bytes" + "context" + "log/slog" + "os" + "strings" + "sync" + "testing" +) + +// mockBridge simulates go-log's slog bridge for testing duck typing detection +type mockBridge struct { + sync.Mutex + slog.Handler + logs *bytes.Buffer +} + +func (m *mockBridge) Handle(_ context.Context, r slog.Record) error { + m.Lock() + defer m.Unlock() + m.logs.WriteString(r.Message) + m.logs.WriteString("\n") + return nil +} + +func (m *mockBridge) WithAttrs(_ []slog.Attr) slog.Handler { + // Simple mock - just return self + return m +} + +// TestGoLogBridgeDetection verifies the duck typing mechanism that detects +// go-log's slog bridge without requiring a direct dependency. This is the core +// integration mechanism that allows gologshim to work with go-log when available. +func TestGoLogBridgeDetection(t *testing.T) { + // Save and restore original default + originalDefault := slog.Default() + defer slog.SetDefault(originalDefault) + + t.Run("bridge detected when present", func(t *testing.T) { + // When go-log's bridge is installed, Logger() should detect it via + // the GoLogBridge() marker method and use it for logging + var buf bytes.Buffer + bridge := &mockBridge{ + Handler: slog.NewTextHandler(&buf, nil), + logs: &buf, + } + SetDefaultHandler(bridge) + + // Create logger - should detect bridge + log := Logger("test-subsystem") + log.Info("test message") + + output := buf.String() + if !strings.Contains(output, "test message") { + t.Errorf("Expected bridge to handle log, got: %s", output) + } + }) + + t.Run("fallback when bridge not present", func(_ *testing.T) { + // When go-log is not available, Logger() should create a fallback + // handler that writes to stderr. This ensures gologshim works standalone. + var buf bytes.Buffer + handler := slog.NewTextHandler(&buf, nil) + slog.SetDefault(slog.New(handler)) + + // Create logger - should use fallback + log := Logger("test-fallback") + + // Fallback writes to stderr, but we can verify it doesn't panic + log.Info("fallback message") + }) +} + +// TestLazyBridgeInitialization verifies the lazy handler solves initialization +// order issues. Package-level logger variables are initialized before go-log's +// init() runs, so the lazy handler defers bridge detection until first log call. +func TestLazyBridgeInitialization(t *testing.T) { + // Save and restore original default + originalDefault := slog.Default() + defer slog.SetDefault(originalDefault) + + // Simulate initialization order: gologshim.Logger() called before go-log loads + var initialBuf bytes.Buffer + slog.SetDefault(slog.New(slog.NewTextHandler(&initialBuf, nil))) + + // Create logger BEFORE bridge is installed (mimics package-level var log = Logger("foo")) + log := Logger("test-lazy") + + // Now install the bridge (mimics go-log's init() running) + var bridgeBuf bytes.Buffer + bridge := &mockBridge{ + Handler: slog.NewTextHandler(&bridgeBuf, nil), + logs: &bridgeBuf, + } + SetDefaultHandler(bridge) + + // Log in goroutine to detect races + go log.Info("lazy init message") + // First log call should detect the bridge via lazy initialization + log.Info("lazy init message") + + bridge.Lock() + output := bridgeBuf.String() + bridge.Unlock() + if !strings.Contains(output, "lazy init message") { + t.Errorf("Lazy handler should have detected bridge, got: %s", output) + } +} + +// TestConfigFromEnv verifies environment variable parsing for all GOLOG_* vars. +// These env vars configure logging behavior and must be compatible with go-log. +func TestConfigFromEnv(t *testing.T) { + // Save and restore env vars + originalLevel := os.Getenv("GOLOG_LOG_LEVEL") + originalFormat := os.Getenv("GOLOG_LOG_FORMAT") + originalLabels := os.Getenv("GOLOG_LOG_LABELS") + defer func() { + os.Setenv("GOLOG_LOG_LEVEL", originalLevel) + os.Setenv("GOLOG_LOG_FORMAT", originalFormat) + os.Setenv("GOLOG_LOG_LABELS", originalLabels) + }() + + t.Run("parse GOLOG_LOG_LEVEL", func(t *testing.T) { + // GOLOG_LOG_LEVEL supports per-subsystem levels: "error,ping=debug,swarm=info" + os.Setenv("GOLOG_LOG_LEVEL", "error,test-subsystem=debug,another=info") + + // Force re-evaluation by calling parseIPFSGoLogEnv directly + fallback, systemToLevel, err := parseIPFSGoLogEnv(os.Getenv("GOLOG_LOG_LEVEL")) + if err != nil { + t.Fatalf("Failed to parse GOLOG_LOG_LEVEL: %v", err) + } + + if fallback != slog.LevelError { + t.Errorf("Expected fallback level ERROR, got %v", fallback) + } + + if systemToLevel["test-subsystem"] != slog.LevelDebug { + t.Errorf("Expected test-subsystem level DEBUG, got %v", systemToLevel["test-subsystem"]) + } + + if systemToLevel["another"] != slog.LevelInfo { + t.Errorf("Expected another level INFO, got %v", systemToLevel["another"]) + } + }) + + t.Run("parse GOLOG_LOG_FORMAT", func(t *testing.T) { + // GOLOG_LOG_FORMAT controls output format: "json" or text (default) + os.Setenv("GOLOG_LOG_FORMAT", "json") + os.Setenv("GOLOG_LOG_LEVEL", "") + + // Note: ConfigFromEnv is cached via sync.OnceValue, so we test the parsing directly + // In real usage, this would be set before first Logger() call + logFmt := os.Getenv("GOLOG_LOG_FORMAT") + if logFmt != "json" { + t.Errorf("Expected format json, got %s", logFmt) + } + }) + + t.Run("parse GOLOG_LOG_LABELS", func(t *testing.T) { + // GOLOG_LOG_LABELS adds key=value pairs to all logs: "app=myapp,dc=us-west" + os.Setenv("GOLOG_LOG_LABELS", "app=test-app,dc=us-west") + + labels := os.Getenv("GOLOG_LOG_LABELS") + if !strings.Contains(labels, "app=test-app") { + t.Error("Expected labels to contain app=test-app") + } + if !strings.Contains(labels, "dc=us-west") { + t.Error("Expected labels to contain dc=us-west") + } + }) +} + +// TestParseIPFSGoLogEnv verifies the GOLOG_LOG_LEVEL parser handles all valid +// formats and returns appropriate errors for invalid input. This parser must +// remain compatible with go-log's format. +func TestParseIPFSGoLogEnv(t *testing.T) { + tests := []struct { + name string + input string + wantFallback slog.Level + wantSubsystems map[string]slog.Level + wantErr bool + }{ + { + name: "empty string uses default level", + input: "", + wantFallback: slog.LevelError, + wantSubsystems: nil, + wantErr: false, + }, + { + name: "fallback only sets global level", + input: "debug", + wantFallback: slog.LevelDebug, + wantSubsystems: nil, + wantErr: false, + }, + { + name: "fallback and subsystems", + input: "error,ping=debug,swarm=info", + wantFallback: slog.LevelError, + wantSubsystems: map[string]slog.Level{ + "ping": slog.LevelDebug, + "swarm": slog.LevelInfo, + }, + wantErr: false, + }, + { + name: "invalid level returns error", + input: "invalid-level", + wantFallback: slog.LevelError, + wantSubsystems: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fallback, subsystems, err := parseIPFSGoLogEnv(tt.input) + + if (err != nil) != tt.wantErr { + t.Errorf("parseIPFSGoLogEnv() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if err != nil { + return + } + + if fallback != tt.wantFallback { + t.Errorf("fallback = %v, want %v", fallback, tt.wantFallback) + } + + if len(subsystems) != len(tt.wantSubsystems) { + t.Errorf("subsystems length = %d, want %d", len(subsystems), len(tt.wantSubsystems)) + } + + for k, v := range tt.wantSubsystems { + if subsystems[k] != v { + t.Errorf("subsystems[%s] = %v, want %v", k, subsystems[k], v) + } + } + }) + } +} diff --git a/libp2p_test.go b/libp2p_test.go index c35ce8a9b..7a7c6b7bf 100644 --- a/libp2p_test.go +++ b/libp2p_test.go @@ -51,7 +51,7 @@ import ( ) func TestNewHost(t *testing.T) { - h, err := makeRandomHost(t, 9000) + h, err := makeRandomHost(t, 9191) if err != nil { t.Fatal(err) } @@ -759,18 +759,18 @@ func TestSharedTCPAddr(t *testing.T) { ShareTCPListener(), Transport(tcp.NewTCPTransport), Transport(websocket.New), - ListenAddrStrings("/ip4/0.0.0.0/tcp/8888"), - ListenAddrStrings("/ip4/0.0.0.0/tcp/8888/ws"), + ListenAddrStrings("/ip4/0.0.0.0/tcp/8188"), + ListenAddrStrings("/ip4/0.0.0.0/tcp/8188/ws"), ) require.NoError(t, err) defer h.Close() sawTCP := false sawWS := false for _, addr := range h.Addrs() { - if strings.HasSuffix(addr.String(), "/tcp/8888") { + if strings.HasSuffix(addr.String(), "/tcp/8188") { sawTCP = true } - if strings.HasSuffix(addr.String(), "/tcp/8888/ws") { + if strings.HasSuffix(addr.String(), "/tcp/8188/ws") { sawWS = true } } diff --git a/p2p/discovery/mdns/mdns.go b/p2p/discovery/mdns/mdns.go index 3a5e7a0ed..5c2692893 100644 --- a/p2p/discovery/mdns/mdns.go +++ b/p2p/discovery/mdns/mdns.go @@ -15,7 +15,6 @@ import ( logging "github.com/libp2p/go-libp2p/gologshim" ma "github.com/multiformats/go-multiaddr" - manet "github.com/multiformats/go-multiaddr/net" ) const ( @@ -109,6 +108,68 @@ func (s *mdnsService) getIPs(addrs []ma.Multiaddr) ([]string, error) { return ips, nil } +// containsUnsuitableProtocol returns true if the multiaddr includes protocols +// that are not suitable for mDNS advertisement: +// - Circuit relay (requires intermediary, not direct LAN connectivity) +// - Browser transports: WebTransport, WebRTC, WebSocket (browsers don't use mDNS) +func containsUnsuitableProtocol(addr ma.Multiaddr) bool { + found := false + ma.ForEach(addr, func(c ma.Component) bool { + switch c.Protocol().Code { + case ma.P_CIRCUIT, + ma.P_WEBTRANSPORT, + ma.P_WEBRTC, + ma.P_WEBRTC_DIRECT, + ma.P_P2P_WEBRTC_DIRECT, + ma.P_WS, + ma.P_WSS: + found = true + return false + } + return true + }) + return found +} + +// isSuitableForMDNS returns true for multiaddrs that should be advertised +// via mDNS. +// +// For an address to be suitable: +// 1. It must start with /ip4, /ip6, or a .local DNS name. The .local TLD is +// reserved for mDNS (RFC 6762) and resolved via multicast, not unicast DNS. +// Non-.local DNS names are filtered out as they require external DNS. +// 2. It must not use circuit relay or browser-only transports (WebTransport, +// WebRTC, WebSocket) because these are not useful for direct LAN discovery. +// +// Filtering reduces mDNS packet size, helping stay within the recommended +// 1500-byte limit per RFC 6762. See: https://github.com/libp2p/go-libp2p/issues/3415 +func isSuitableForMDNS(addr ma.Multiaddr) bool { + if addr == nil { + return false + } + + first, _ := ma.SplitFirst(addr) + if first == nil { + return false + } + + // Check the addressing scheme + switch first.Protocol().Code { + case ma.P_IP4, ma.P_IP6: + // Direct IP addresses are always suitable for LAN discovery + case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR: + // DNS names are only suitable if they're in the .local TLD, + // which is resolved via mDNS (RFC 6762), not unicast DNS. + if !strings.HasSuffix(strings.ToLower(first.Value()), ".local") { + return false + } + default: + return false + } + + return !containsUnsuitableProtocol(addr) +} + func (s *mdnsService) startServer() error { interfaceAddrs, err := s.host.Network().InterfaceListenAddresses() if err != nil { @@ -121,9 +182,10 @@ func (s *mdnsService) startServer() error { if err != nil { return err } + // Build TXT records for addresses suitable for mDNS advertisement. var txts []string for _, addr := range addrs { - if manet.IsThinWaist(addr) { // don't announce circuit addresses + if isSuitableForMDNS(addr) { txts = append(txts, dnsaddrPrefix+addr.String()) } } diff --git a/p2p/discovery/mdns/mdns_test.go b/p2p/discovery/mdns/mdns_test.go index de981b5bd..cfef3cc2e 100644 --- a/p2p/discovery/mdns/mdns_test.go +++ b/p2p/discovery/mdns/mdns_test.go @@ -10,6 +10,7 @@ import ( "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" + ma "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -102,3 +103,54 @@ func TestOtherDiscovery(t *testing.T) { "expected peers to find each other", ) } + +func TestIsSuitableForMDNS(t *testing.T) { + tests := []struct { + name string + addr string + expected bool + }{ + // IP addresses with native transports - suitable for mDNS + {"tcp", "/ip4/192.168.1.1/tcp/4001", true}, + {"quic-v1", "/ip4/192.168.1.2/udp/4001/quic-v1", true}, + {"tcp-ipv6", "/ip6/fe80::1/tcp/4001", true}, + {"quic-v1-ipv6", "/ip6/fe80::2/udp/4001/quic-v1", true}, + + // Browser transports - NOT suitable for mDNS + // (browsers don't use mDNS for peer discovery) + {"webtransport", "/ip4/192.168.1.1/udp/4001/quic-v1/webtransport", false}, + {"webrtc", "/ip4/192.168.1.1/udp/4001/webrtc/certhash/uEiAkH5a4DPGKUuOBjYw0CgwjLa2R_RF71v86aVxlqdKNOQ", false}, + {"webrtc-direct", "/ip4/192.168.1.1/udp/4001/webrtc-direct", false}, + {"ws", "/ip4/192.168.1.1/tcp/4001/ws", false}, + {"wss", "/ip4/192.168.1.1/tcp/443/wss", false}, + + // .local DNS names - suitable for mDNS + // (.local TLD is resolved via mDNS per RFC 6762) + {"dns-local", "/dns/myhost.local/tcp/4001", true}, + {"dns4-local", "/dns4/myhost.local/tcp/4001", true}, + {"dns6-local", "/dns6/myhost.local/tcp/4001", true}, + {"dnsaddr-local", "/dnsaddr/myhost.local/tcp/4001", true}, + {"dns-local-mixed-case", "/dns4/MyHost.LOCAL/tcp/4001", true}, + + // Non-.local DNS names - NOT suitable for mDNS + // (require unicast DNS resolution, not mDNS) + {"dns4-public", "/dns4/example.com/tcp/4001", false}, + {"dns6-public", "/dns6/example.com/tcp/4001", false}, + {"dnsaddr-public", "/dnsaddr/example.com/tcp/4001", false}, + {"dns-local-suffix-not-tld", "/dns4/notlocal.com/tcp/4001", false}, + {"dns-fake-local", "/dns4/local.example.com/tcp/4001", false}, + {"libp2p-direct", "/dns4/192-0-2-1.k51qzi5uqu5dgutdk6i1ynyzgkqngpha5xpgia3a5qqp4jsh0u4csozksxel3r.libp2p.direct/tcp/30895/tls/ws", false}, + + // Circuit relay addresses - NOT suitable for mDNS + // (require relay node, not direct LAN connectivity) + {"circuit-relay", "/ip4/198.51.100.1/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN/p2p-circuit/p2p/12D3KooWGzBXWNvHpLALvz3jhwdCF6kfv9MfhMn9CuS2MBD2GpSy", false}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + addr, err := ma.NewMultiaddr(tc.addr) + require.NoError(t, err) + got := isSuitableForMDNS(addr) + assert.Equal(t, tc.expected, got, "isSuitableForMDNS(%s)", tc.addr) + }) + } +} diff --git a/p2p/host/autorelay/autorelay_test.go b/p2p/host/autorelay/autorelay_test.go index a2186b518..3a280ac38 100644 --- a/p2p/host/autorelay/autorelay_test.go +++ b/p2p/host/autorelay/autorelay_test.go @@ -320,11 +320,11 @@ func TestConnectOnDisconnect(t *testing.T) { r.Close() } } - - require.Eventually(t, func() bool { return numRelays(h) > 0 }, 10*time.Second, 100*time.Millisecond) - relaysInUse = usedRelays(h) - require.Len(t, relaysInUse, 1) - require.NotEqualf(t, oldRelay, relaysInUse[0], "old relay should not be used again") + require.EventuallyWithT(t, func(collect *assert.CollectT) { + relaysInUse = usedRelays(h) + assert.Len(collect, relaysInUse, 1) + assert.NotEqualf(collect, oldRelay, relaysInUse[0], "old relay should not be used again") + }, 10*time.Second, 100*time.Millisecond) } func TestMaxAge(t *testing.T) { diff --git a/p2p/host/basic/addrs_reachability_tracker.go b/p2p/host/basic/addrs_reachability_tracker.go index d2a370b90..0f802977d 100644 --- a/p2p/host/basic/addrs_reachability_tracker.go +++ b/p2p/host/basic/addrs_reachability_tracker.go @@ -361,10 +361,6 @@ const ( // and then a success(...S S S S F S). The confidence in the targetConfidence window will be equal to // targetConfidence, the last F and S cancel each other, and we won't probe again for maxProbeInterval. maxRecentDialsWindow = targetConfidence + 2 - // secondaryAddrsScalingFactor is the multiplier applied to secondary address dial outcomes. For secondary - // addr, if the primary addr is reachable, a single successful dial is enough to consider the secondary addr - // reachable. - secondaryAddrsScalingFactor = targetConfidence // highConfidenceAddrProbeInterval is the maximum interval between probes for an address highConfidenceAddrProbeInterval = 1 * time.Hour // highConfidenceSecondaryAddrProbeInterval is the maximum interval between probes for an address @@ -620,6 +616,19 @@ func (s *addrStatus) Reachability() network.Reachability { } func (s *addrStatus) RequiredProbeCount(now time.Time) int { + // Secondary addresses inherit reachability from their confirmed-public primary. + // If the primary is ReachabilityPublic, the port is confirmed open at the + // network level, so the secondary is also reachable (they share the socket). + // + // If the primary is ReachabilityPrivate, we still probe the secondary because + // Private is a weaker signal - it could indicate: + // - Port genuinely blocked (secondary will also fail) + // - Protocol-specific issues with the primary (secondary might work) + // The cost of extra probes when truly firewalled is low (quick failures). + if s.primary != nil && s.primary.Reachability() == network.ReachabilityPublic { + return 0 + } + if s.consecutiveRefusals >= maxConsecutiveRefusals { if now.Sub(s.lastRefusalTime) < recentProbeInterval { return 0 @@ -742,12 +751,49 @@ func (s *addrStatus) reachabilityAndCounts() (rch network.Reachability, successe } if s.primary != nil { prch, _, _ := s.primary.reachabilityAndCounts() - switch prch { - case network.ReachabilityPublic: - successes *= secondaryAddrsScalingFactor - case network.ReachabilityPrivate: - failures *= secondaryAddrsScalingFactor + if prch == network.ReachabilityPublic { + // Secondary transports inherit Public reachability from their primary. + // + // This is important because not all AutoNAT v2 server implementations + // support all secondary transports. As the Amino DHT gained a more + // diverse set of node implementations (2025 Q4), we observed false + // negatives: secondary addresses being marked unreachable when probing + // peers simply didn't support the protocol, not because the port was + // actually blocked. + // + // This handles shared-listener configurations where multiple + // protocols share the same network socket: + // + // TCP-based (libp2p.ShareTCPListener): + // Primary: /ip4/.../tcp/port + // Secondary: /ip4/.../tcp/port/tls/sni/*.libp2p.direct/ws + // TCP and Secure WebSocket share the same TCP listener. + // + // UDP/QUIC-based (quicreuse.ConnManager): + // Primary: /ip4/.../udp/port/quic-v1 + // Secondary: /ip4/.../udp/port/quic-v1/webtransport + // Secondary: /ip4/.../udp/port/webrtc-direct + // QUIC, WebTransport, and WebRTC share the same UDP socket. + // + // AutoNAT v2 probe failures for secondary protocols typically + // indicate protocol incompatibility at the probing peer, not + // port unreachability: + // + // - Secure WebSocket: Probing peer may not support WebSockets, + // or TLS handshake fails because the certificate isn't + // provisioned yet (AutoTLS still obtaining cert). + // - WebTransport: Probing peer supports QUIC but not HTTP/3. + // - WebRTC: Probing peer supports QUIC but not DTLS-SRTP. + // + // Since the primary confirms the port is network-reachable, we + // inherit that status. Protocol-level failures don't indicate + // the address is unreachable to peers that DO support the protocol. + return network.ReachabilityPublic, successes, failures } + // If primary is Private or Unknown, we don't inherit - the secondary + // builds its own status through probing. This is more conservative: + // Private could indicate protocol-specific issues rather than port + // unreachability, so we give the secondary a chance to prove itself. } if successes-failures >= minConfidence { return network.ReachabilityPublic, successes, failures diff --git a/p2p/host/basic/addrs_reachability_tracker_test.go b/p2p/host/basic/addrs_reachability_tracker_test.go index f1c35d4ba..c6a69f079 100644 --- a/p2p/host/basic/addrs_reachability_tracker_test.go +++ b/p2p/host/basic/addrs_reachability_tracker_test.go @@ -209,71 +209,88 @@ func TestProbeManager(t *testing.T) { } return res } - // tcp private + + // Conservative inheritance: secondaries only inherit Public from primary. + // If primary is Private, secondaries still get probed (Private could be + // protocol-specific, not port-level). + // + // TCP gets Public results - websocket inherits Public (skips probing) + // This is the AutoTLS use case: TCP works, WSS inherits reachability. + for i := range targetConfidence { + reqs := nextProbe(pm) + if i < minConfidence { + // TCP not yet confirmed Public, all 4 addresses need probing + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic, websocket, webrtc}, extractAddrs(reqs)) + } else { + // TCP confirmed Public, websocket inherits - only 3 addresses + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic, webrtc}, extractAddrs(reqs)) + } + pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPublic}, nil) + } + + // QUIC gets Private results - webrtc still needs probing (no inheritance) + // This tests the conservative behavior: Private doesn't propagate. for range targetConfidence { reqs := nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic, websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) + // websocket already inherited from tcp, but webrtc doesn't inherit Private + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic, webrtc}, extractAddrs(reqs)) + pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) } - // quic public - for range targetConfidence { - reqs := nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic, websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPublic}, nil) - } - // only 1 check now required for websocket - for range 1 { - reqs := nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: websocket, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) - } - // 3 checks required for webrtc to make its reachability different from quic. + + // webrtc still needs probing (doesn't inherit Private from quic) + // Give webrtc its own Private status through probing for range targetConfidence { reqs := nextProbe(pm) matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{webrtc}, extractAddrs(reqs)) pm.CompleteProbe(reqs, autonatv2.Result{Addr: webrtc, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) } - reachable, unreachable, _ := pm.AppendConfirmedAddrs(nil, nil, nil) - matest.AssertMultiaddrsMatch(t, []ma.Multiaddr{quic}, reachable) - matest.AssertMultiaddrsMatch(t, []ma.Multiaddr{tcp, websocket, webrtc}, unreachable) + reqs := nextProbe(pm) + require.Empty(t, reqs) - // Every `highConfidenceAddrsProbeInterval` we refresh the primary addr binding + reachable, unreachable, _ := pm.AppendConfirmedAddrs(nil, nil, nil) + // websocket inherits Public from tcp (confirmed reachable port) - AutoTLS case + // webrtc has its own Private status (probed independently) + matest.AssertMultiaddrsMatch(t, []ma.Multiaddr{tcp, websocket}, reachable) + matest.AssertMultiaddrsMatch(t, []ma.Multiaddr{quic, webrtc}, unreachable) + + // After highConfidenceAddrProbeInterval (1h), only primaries need refresh. + // websocket inherits from tcp (Public), webrtc has longer refresh interval (3h). for range 2 { cl.Add(highConfidenceAddrProbeInterval + 1*time.Millisecond) reqs := nextProbe(pm) + // Only tcp and quic need refresh; websocket inherits, webrtc has 3h interval matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) + pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPublic}, nil) reqs = nextProbe(pm) matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPublic}, nil) + pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) reqs = nextProbe(pm) require.Empty(t, reqs) } - cl.Add(highConfidenceAddrProbeInterval + 1*time.Millisecond) - reqs := nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic, websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) - reqs = nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic, websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPublic}, nil) + reachable, unreachable, _ = pm.AppendConfirmedAddrs(nil, nil, nil) + matest.AssertMultiaddrsMatch(t, reachable, []ma.Multiaddr{tcp, websocket}) + matest.AssertMultiaddrsMatch(t, unreachable, []ma.Multiaddr{quic, webrtc}) - // secondary addrs refreshed at 3*highConfidenceProbeInterval + // After highConfidenceSecondaryAddrProbeInterval (3h), webrtc needs refresh too. + // We've advanced 2h+2ms, need to reach 3h+ for webrtc's refresh. + // Also need to exceed 1h since last tcp/quic refresh for them to need refresh. + cl.Add(highConfidenceSecondaryAddrProbeInterval - 2*highConfidenceAddrProbeInterval + 1*time.Millisecond) reqs = nextProbe(pm) - matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{websocket, webrtc}, extractAddrs(reqs)) - pm.CompleteProbe(reqs, autonatv2.Result{Addr: websocket, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) + // tcp, quic, and webrtc need refresh; websocket still inherits from tcp + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{tcp, quic, webrtc}, extractAddrs(reqs)) + pm.CompleteProbe(reqs, autonatv2.Result{Addr: tcp, Idx: 0, Reachability: network.ReachabilityPublic}, nil) + reqs = nextProbe(pm) + matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic, webrtc}, extractAddrs(reqs)) + pm.CompleteProbe(reqs, autonatv2.Result{Addr: quic, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) reqs = nextProbe(pm) matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{webrtc}, extractAddrs(reqs)) pm.CompleteProbe(reqs, autonatv2.Result{Addr: webrtc, Idx: 0, Reachability: network.ReachabilityPrivate}, nil) reqs = nextProbe(pm) require.Empty(t, reqs) - - reachable, unreachable, _ = pm.AppendConfirmedAddrs(nil, nil, nil) - matest.AssertMultiaddrsMatch(t, reachable, []ma.Multiaddr{quic}) - matest.AssertMultiaddrsMatch(t, unreachable, []ma.Multiaddr{tcp, websocket, webrtc}) }) } diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index d98aa0e33..abd18795c 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -683,6 +683,11 @@ func (s *streamWrapper) Write(b []byte) (int, error) { } func (s *streamWrapper) Close() error { + // Set a read deadline to prevent Close() from blocking indefinitely + // waiting for the multistream-select handshake to complete. + // This can happen when the remote peer is slow or unresponsive. + // See: https://github.com/multiformats/go-multistream/issues/47 + _ = s.Stream.SetReadDeadline(time.Now().Add(DefaultNegotiationTimeout)) return s.rw.Close() } diff --git a/p2p/host/basic/basic_host_synctest_test.go b/p2p/host/basic/basic_host_synctest_test.go new file mode 100644 index 000000000..eb78cfcbc --- /dev/null +++ b/p2p/host/basic/basic_host_synctest_test.go @@ -0,0 +1,81 @@ +//go:build go1.25 + +package basichost_test + +import ( + "testing" + "testing/synctest" + "time" + + "github.com/libp2p/go-libp2p/core/network" + basichost "github.com/libp2p/go-libp2p/p2p/host/basic" + "github.com/libp2p/go-libp2p/x/simlibp2p" + + "github.com/stretchr/testify/require" +) + +// TestStreamCloseDoesNotHangOnUnresponsivePeer verifies that stream.Close() +// returns within DefaultNegotiationTimeout even when the remote peer never +// completes the multistream handshake. Without the read deadline fix in +// streamWrapper.Close(), this would hang indefinitely. +func TestStreamCloseDoesNotHangOnUnresponsivePeer_synctest(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + ctx := t.Context() + + h1, h2 := simlibp2p.GetBasicHostPair(t) + defer h1.Close() + defer h2.Close() + + const testProto = "/test/hang" + + // Manually add protocol to peerstore so h1 thinks h2 supports it. + // This makes NewStream use lazy multistream (skipping negotiation until Close). + h1.Peerstore().AddProtocols(h2.ID(), testProto) + + // h2 accepts streams at the network level but never responds to + // multistream protocol negotiation, simulating an unresponsive peer. + h2.Network().SetStreamHandler(func(s network.Stream) { + // Read incoming data but never write back - simulates unresponsive peer + buf := make([]byte, 1024) + for { + _, err := s.Read(buf) + if err != nil { + return + } + } + }) + + // Open stream to h2 - uses lazy multistream because protocol is "known" + s, err := h1.NewStream(ctx, h2.ID(), testProto) + require.NoError(t, err) + + // Trigger the lazy handshake by writing data. + // The write succeeds (buffered), but the read handshake will block + // because h2 never sends a response. + _, err = s.Write([]byte("trigger handshake")) + require.NoError(t, err) + + // Close() should return within DefaultNegotiationTimeout because the fix + // sets a read deadline before calling the underlying Close(). + // Without the fix, this would hang indefinitely. + elapsedCh := make(chan time.Duration) + go func() { + start := time.Now() + _ = s.Close() + elapsedCh <- time.Since(start) + }() + + maxExpected := basichost.DefaultNegotiationTimeout + var elapsed time.Duration + select { + case elapsed = <-elapsedCh: + case <-time.After(maxExpected + time.Second): + t.Fatal("timeout waiting for Close()") + } + + require.Equal(t, elapsed, maxExpected, + "Close() took %v, expected < %v (DefaultNegotiationTimeout + margin)", elapsed, maxExpected) + + t.Logf("Close() returned in %v (limit: %v)", elapsed, maxExpected) + }) +} diff --git a/p2p/host/basic/basic_host_test.go b/p2p/host/basic/basic_host_test.go index 07f82825f..2ecd22f10 100644 --- a/p2p/host/basic/basic_host_test.go +++ b/p2p/host/basic/basic_host_test.go @@ -224,8 +224,8 @@ func TestAllAddrs(t *testing.T) { // listen on IPv4 0.0.0.0 require.NoError(t, h.Network().Listen(ma.StringCast("/ip4/0.0.0.0/tcp/0"))) - // should contain localhost and private local addr along with previous listen address - require.Len(t, h.AllAddrs(), 3) + // should contain more addresses than just the one from last time + require.Greater(t, len(h.AllAddrs()), 1) // Should still contain the original addr. require.True(t, ma.Contains(h.AllAddrs(), firstAddr), "should still contain the original addr") } diff --git a/p2p/host/resource-manager/limits_metrics_test.go b/p2p/host/resource-manager/limits_metrics_test.go new file mode 100644 index 000000000..ccfb8d45c --- /dev/null +++ b/p2p/host/resource-manager/limits_metrics_test.go @@ -0,0 +1,149 @@ +package rcmgr + +import ( + "testing" + + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" +) + +func TestReportSystemLimits(t *testing.T) { + // Register the metrics + reg := prometheus.NewRegistry() + reg.MustRegister(limits) + + // Create a simple limiter with known limits + limiter := NewFixedLimiter(ConcreteLimitConfig{ + system: BaseLimit{ + Memory: 1024 * 1024 * 1024, // 1GB + FD: 256, + Conns: 100, + ConnsInbound: 50, + ConnsOutbound: 50, + Streams: 200, + StreamsInbound: 100, + StreamsOutbound: 100, + }, + transient: BaseLimit{ + Memory: 512 * 1024 * 1024, // 512MB + FD: 128, + Conns: 50, + ConnsInbound: 25, + ConnsOutbound: 25, + Streams: 100, + StreamsInbound: 50, + StreamsOutbound: 50, + }, + }) + + // Create a stats reporter + reporter, err := NewStatsTraceReporter() + if err != nil { + t.Fatal(err) + } + + // Report the limits + reporter.ReportSystemLimits(limiter) + + // Verify that metrics were set + metrics, err := reg.Gather() + if err != nil { + t.Fatal(err) + } + + // Find the limits metric + var limitsMetric *dto.MetricFamily + for _, m := range metrics { + if m.GetName() == "libp2p_rcmgr_limit" { + limitsMetric = m + break + } + } + + if limitsMetric == nil { + t.Fatal("limits metric not found") + } + + // Verify we have metrics for both system and transient scopes + foundSystem := false + foundTransient := false + for _, metric := range limitsMetric.GetMetric() { + for _, label := range metric.GetLabel() { + if label.GetName() == "scope" { + if label.GetValue() == "system" { + foundSystem = true + } + if label.GetValue() == "transient" { + foundTransient = true + } + } + } + } + + if !foundSystem { + t.Error("system scope limits not reported") + } + if !foundTransient { + t.Error("transient scope limits not reported") + } + + // Verify specific limit values + expectedLimits := map[string]map[string]float64{ + "system": { + "memory": 1024 * 1024 * 1024, + "fd": 256, + "conns": 100, + "conns_inbound": 50, + "conns_outbound": 50, + "streams": 200, + "streams_inbound": 100, + "streams_outbound": 100, + }, + "transient": { + "memory": 512 * 1024 * 1024, + "fd": 128, + "conns": 50, + "conns_inbound": 25, + "conns_outbound": 25, + "streams": 100, + "streams_inbound": 50, + "streams_outbound": 50, + }, + } + + for _, metric := range limitsMetric.GetMetric() { + var scope, resource string + for _, label := range metric.GetLabel() { + if label.GetName() == "scope" { + scope = label.GetValue() + } + if label.GetName() == "resource" { + resource = label.GetValue() + } + } + + if scope == "" || resource == "" { + continue + } + + expectedValue, ok := expectedLimits[scope][resource] + if !ok { + continue + } + + actualValue := metric.GetGauge().GetValue() + if actualValue != expectedValue { + t.Errorf("limit mismatch for %s/%s: expected %v, got %v", scope, resource, expectedValue, actualValue) + } + } +} + +func TestReportSystemLimitsNilLimiter(t *testing.T) { + reporter, err := NewStatsTraceReporter() + if err != nil { + t.Fatal(err) + } + + // Should not panic with nil limiter + reporter.ReportSystemLimits(nil) +} diff --git a/p2p/host/resource-manager/rcmgr.go b/p2p/host/resource-manager/rcmgr.go index efacb4547..52561ff29 100644 --- a/p2p/host/resource-manager/rcmgr.go +++ b/p2p/host/resource-manager/rcmgr.go @@ -178,17 +178,20 @@ func NewResourceManager(limits Limiter, opts ...Option) (network.ResourceManager r.verifySourceAddressRateLimiter = newVerifySourceAddressRateLimiter(r.connLimiter) if !r.disableMetrics { - var sr TraceReporter sr, err := NewStatsTraceReporter() if err != nil { log.Error("failed to initialise StatsTraceReporter", "err", err) } else { + // Report system limits to Prometheus + sr.ReportSystemLimits(limits) + if r.trace == nil { r.trace = &trace{} } found := false for _, rep := range r.trace.reporters { - if rep == sr { + // Compare the actual reporter, not the interface + if _, ok := rep.(StatsTraceReporter); ok { found = true break } diff --git a/p2p/host/resource-manager/stats.go b/p2p/host/resource-manager/stats.go index fd0772948..c43b4f25b 100644 --- a/p2p/host/resource-manager/stats.go +++ b/p2p/host/resource-manager/stats.go @@ -3,6 +3,7 @@ package rcmgr import ( "strings" + "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/p2p/metricshelper" "github.com/prometheus/client_golang/prometheus" ) @@ -123,6 +124,13 @@ var ( Name: "blocked_resources", Help: "Number of blocked resources", }, []string{"dir", "scope", "resource"}) + + // System limits + limits = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: metricNamespace, + Name: "limit", + Help: "Resource manager limits", + }, []string{"scope", "resource"}) ) var ( @@ -157,6 +165,7 @@ func MustRegisterWith(reg prometheus.Registerer) { previousConnMemory, fds, blockedResources, + limits, ) } @@ -171,10 +180,47 @@ func WithMetricsDisabled() Option { type StatsTraceReporter struct{} func NewStatsTraceReporter() (StatsTraceReporter, error) { - // TODO tell prometheus the system limits return StatsTraceReporter{}, nil } +// reportLimit reports a limit value to Prometheus +func reportLimit(scope, resource string, value int64) { + limits.With(prometheus.Labels{ + "scope": scope, + "resource": resource, + }).Set(float64(value)) +} + +// ReportSystemLimits reports the system limits to Prometheus. +// This should be called after creating the StatsTraceReporter with the resource manager's limits. +func (r StatsTraceReporter) ReportSystemLimits(limiter Limiter) { + if limiter == nil { + return + } + + // System limits + systemLimits := limiter.GetSystemLimits() + reportLimit("system", "memory", systemLimits.GetMemoryLimit()) + reportLimit("system", "fd", int64(systemLimits.GetFDLimit())) + reportLimit("system", "conns", int64(systemLimits.GetConnTotalLimit())) + reportLimit("system", "conns_inbound", int64(systemLimits.GetConnLimit(network.DirInbound))) + reportLimit("system", "conns_outbound", int64(systemLimits.GetConnLimit(network.DirOutbound))) + reportLimit("system", "streams", int64(systemLimits.GetStreamTotalLimit())) + reportLimit("system", "streams_inbound", int64(systemLimits.GetStreamLimit(network.DirInbound))) + reportLimit("system", "streams_outbound", int64(systemLimits.GetStreamLimit(network.DirOutbound))) + + // Transient limits + transientLimits := limiter.GetTransientLimits() + reportLimit("transient", "memory", transientLimits.GetMemoryLimit()) + reportLimit("transient", "fd", int64(transientLimits.GetFDLimit())) + reportLimit("transient", "conns", int64(transientLimits.GetConnTotalLimit())) + reportLimit("transient", "conns_inbound", int64(transientLimits.GetConnLimit(network.DirInbound))) + reportLimit("transient", "conns_outbound", int64(transientLimits.GetConnLimit(network.DirOutbound))) + reportLimit("transient", "streams", int64(transientLimits.GetStreamTotalLimit())) + reportLimit("transient", "streams_inbound", int64(transientLimits.GetStreamLimit(network.DirInbound))) + reportLimit("transient", "streams_outbound", int64(transientLimits.GetStreamLimit(network.DirOutbound))) +} + func (r StatsTraceReporter) ConsumeEvent(evt TraceEvt) { tags := metricshelper.GetStringSlice() defer metricshelper.PutStringSlice(tags) diff --git a/p2p/protocol/holepunch/holepunch_test.go b/p2p/protocol/holepunch/holepunch_test.go index b96c94685..0d246fe34 100644 --- a/p2p/protocol/holepunch/holepunch_test.go +++ b/p2p/protocol/holepunch/holepunch_test.go @@ -539,14 +539,15 @@ func TestFailuresOnResponder(t *testing.T) { defer relay.Close() time.Sleep(100 * time.Millisecond) - + // Apparently changing the order of the following two flakiness. + // https://github.com/libp2p/go-libp2p/issues/3440 + require.EventuallyWithT(t, func(c *assert.CollectT) { + assert.Contains(c, h1.Mux().Protocols(), holepunch.Protocol) + }, time.Second, 100*time.Millisecond) require.NoError(t, h1.Connect(context.Background(), peer.AddrInfo{ ID: h2.ID(), Addrs: h2.Addrs(), })) - require.EventuallyWithT(t, func(c *assert.CollectT) { - assert.Contains(c, h1.Mux().Protocols(), holepunch.Protocol) - }, time.Second, 100*time.Millisecond) s, err := h2.NewStream(network.WithAllowLimitedConn(context.Background(), "holepunch"), h1.ID(), holepunch.Protocol) require.NoError(t, err) @@ -636,7 +637,8 @@ func quicSimnet(isPubliclyReachably bool, router *simnet.SimpleFirewallRouter) l if isPubliclyReachably { router.SetAddrPubliclyReachable(address) } - c := simnet.NewSimConn(address, router) + c := simnet.NewSimConn(address) + router.AddNode(address, c) return c, nil })) } diff --git a/p2p/transport/quicreuse/config.go b/p2p/transport/quicreuse/config.go index 62f8919c8..62722082d 100644 --- a/p2p/transport/quicreuse/config.go +++ b/p2p/transport/quicreuse/config.go @@ -15,4 +15,6 @@ var quicConfig = &quic.Config{ Versions: []quic.Version{quic.Version1}, // We don't use datagrams (yet), but this is necessary for WebTransport EnableDatagrams: true, + // Required for WebTransport + EnableStreamResetPartialDelivery: true, } diff --git a/p2p/transport/quicreuse/connmgr.go b/p2p/transport/quicreuse/connmgr.go index e8ace8397..023b82ee0 100644 --- a/p2p/transport/quicreuse/connmgr.go +++ b/p2p/transport/quicreuse/connmgr.go @@ -13,16 +13,18 @@ import ( "net" "sync" + "github.com/libp2p/go-libp2p/gologshim" "github.com/libp2p/go-netroute" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" "github.com/prometheus/client_golang/prometheus" "github.com/quic-go/quic-go" - quiclogging "github.com/quic-go/quic-go/logging" - quicmetrics "github.com/quic-go/quic-go/metrics" + "github.com/quic-go/quic-go/qlog" "golang.org/x/time/rate" ) +var log = gologshim.Logger("quicreuse") + type QUICListener interface { Accept(ctx context.Context) (*quic.Conn, error) Close() error @@ -109,7 +111,8 @@ func NewConnManager(statelessResetKey quic.StatelessResetKey, tokenKey quic.Toke } quicConf := quicConfig.Clone() - quicConf.Tracer = cm.getTracer() + // quic-go takes care of disabling this if QLOGDIR Environment variable isn't present + quicConf.Tracer = qlog.DefaultConnectionTracer serverConfig := quicConf.Clone() cm.clientConfig = quicConf @@ -136,37 +139,6 @@ func NewConnManager(statelessResetKey quic.StatelessResetKey, tokenKey quic.Toke return cm, nil } -func (c *ConnManager) getTracer() func(context.Context, quiclogging.Perspective, quic.ConnectionID) *quiclogging.ConnectionTracer { - return func(_ context.Context, p quiclogging.Perspective, ci quic.ConnectionID) *quiclogging.ConnectionTracer { - var promTracer *quiclogging.ConnectionTracer - if c.enableMetrics { - switch p { - case quiclogging.PerspectiveClient: - promTracer = quicmetrics.NewClientConnectionTracerWithRegisterer(c.registerer) - case quiclogging.PerspectiveServer: - promTracer = quicmetrics.NewServerConnectionTracerWithRegisterer(c.registerer) - default: - log.Error("invalid logging perspective", "peer", p) - } - } - var tracer *quiclogging.ConnectionTracer - var tracerDir = c.qlogTracerDir - if tracerDir == "" { - // Fallback to the global qlogTracerDir - tracerDir = qlogTracerDir - } - - if tracerDir != "" { - tracer = qloggerForDir(tracerDir, p, ci) - if promTracer != nil { - tracer = quiclogging.NewMultiplexedConnectionTracer(promTracer, - tracer) - } - } - return tracer - } -} - func (c *ConnManager) getReuse(network string) (*reuse, error) { switch network { case "udp4": diff --git a/p2p/transport/quicreuse/tracer.go b/p2p/transport/quicreuse/tracer.go deleted file mode 100644 index ce8c2802f..000000000 --- a/p2p/transport/quicreuse/tracer.go +++ /dev/null @@ -1,94 +0,0 @@ -package quicreuse - -import ( - "bufio" - "fmt" - "io" - "os" - "time" - - "github.com/klauspost/compress/zstd" - golog "github.com/libp2p/go-libp2p/gologshim" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/logging" - "github.com/quic-go/quic-go/qlog" -) - -var log = golog.Logger("quic-utils") - -// QLOGTracer holds a qlog tracer dir, if qlogging is enabled (enabled using the QLOGDIR environment variable). -// Otherwise it is an empty string. -var qlogTracerDir string - -func init() { - qlogTracerDir = os.Getenv("QLOGDIR") -} - -func qloggerForDir(qlogDir string, p logging.Perspective, ci quic.ConnectionID) *logging.ConnectionTracer { - // create the QLOGDIR, if it doesn't exist - if err := os.MkdirAll(qlogDir, 0777); err != nil { - log.Error("creating the QLOGDIR failed", "err", err) - return nil - } - return qlog.NewConnectionTracer(newQlogger(qlogDir, p, ci), p, ci) -} - -// The qlogger logs qlog events to a temporary file: ..qlog.swp. -// When it is closed, it compresses the temporary file and saves it as .qlog.zst. -// It is not possible to compress on the fly, as compression algorithms keep a lot of internal state, -// which can easily exhaust the host system's memory when running a few hundred QUIC connections in parallel. -type qlogger struct { - f *os.File // QLOGDIR/.log_xxx.qlog.swp - filename string // QLOGDIR/log_xxx.qlog.zst - *bufio.Writer // buffering the f -} - -func newQlogger(qlogDir string, role logging.Perspective, connID quic.ConnectionID) io.WriteCloser { - t := time.Now().UTC().Format("2006-01-02T15-04-05.999999999UTC") - r := "server" - if role == logging.PerspectiveClient { - r = "client" - } - finalFilename := fmt.Sprintf("%s%clog_%s_%s_%s.qlog.zst", qlogDir, os.PathSeparator, t, r, connID) - filename := fmt.Sprintf("%s%c.log_%s_%s_%s.qlog.swp", qlogDir, os.PathSeparator, t, r, connID) - f, err := os.Create(filename) - if err != nil { - log.Error("unable to create qlog file", "filename", filename, "error", err) - return nil - } - return &qlogger{ - f: f, - filename: finalFilename, - // The size of a qlog file for a raw file download is ~2/3 of the amount of data transferred. - // bufio.NewWriter creates a buffer with a buffer of only 4 kB, leading to a large number of syscalls. - Writer: bufio.NewWriterSize(f, 128<<10), - } -} - -func (l *qlogger) Close() error { - defer os.Remove(l.f.Name()) - defer l.f.Close() - if err := l.Writer.Flush(); err != nil { - return err - } - if _, err := l.f.Seek(0, io.SeekStart); err != nil { // set the read position to the beginning of the file - return err - } - f, err := os.Create(l.filename) - if err != nil { - return err - } - defer f.Close() - buf := bufio.NewWriterSize(f, 128<<10) - c, err := zstd.NewWriter(buf, zstd.WithEncoderLevel(zstd.SpeedFastest), zstd.WithWindowSize(32*1024)) - if err != nil { - return err - } - if _, err := io.Copy(c, l.f); err != nil { - return err - } - if err := c.Close(); err != nil { - return err - } - return buf.Flush() -} diff --git a/p2p/transport/quicreuse/tracer_test.go b/p2p/transport/quicreuse/tracer_test.go deleted file mode 100644 index bea6b91db..000000000 --- a/p2p/transport/quicreuse/tracer_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package quicreuse - -import ( - "bytes" - "io" - "os" - "strings" - "testing" - - "github.com/klauspost/compress/zstd" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/logging" - "github.com/stretchr/testify/require" -) - -func getFile(t *testing.T, dir string) os.FileInfo { - files, err := os.ReadDir(dir) - require.NoError(t, err) - require.Len(t, files, 1) - info, err := files[0].Info() - require.NoError(t, err) - return info -} - -func TestSaveQlog(t *testing.T) { - qlogDir := t.TempDir() - logger := newQlogger(qlogDir, logging.PerspectiveServer, quic.ConnectionIDFromBytes([]byte{0xde, 0xad, 0xbe, 0xef})) - file := getFile(t, qlogDir) - require.Equal(t, ".", string(file.Name()[0])) - require.Truef(t, strings.HasSuffix(file.Name(), ".qlog.swp"), "expected %s to have the .qlog.swp file ending", file.Name()) - // close the logger. This should move the file. - require.NoError(t, logger.Close()) - file = getFile(t, qlogDir) - require.NotEqual(t, ".", string(file.Name()[0])) - require.Truef(t, strings.HasSuffix(file.Name(), ".qlog.zst"), "expected %s to have the .qlog.zst file ending", file.Name()) - require.Contains(t, file.Name(), "server") - require.Contains(t, file.Name(), "deadbeef") -} - -func TestQlogBuffering(t *testing.T) { - qlogDir := t.TempDir() - logger := newQlogger(qlogDir, logging.PerspectiveServer, quic.ConnectionIDFromBytes([]byte("connid"))) - initialSize := getFile(t, qlogDir).Size() - // Do a small write. - // Since the writter is buffered, this should not be written to disk yet. - logger.Write([]byte("foobar")) - require.Equal(t, getFile(t, qlogDir).Size(), initialSize) - // Close the logger. This should flush the buffer to disk. - require.NoError(t, logger.Close()) - finalSize := getFile(t, qlogDir).Size() - t.Logf("initial log file size: %d, final log file size: %d\n", initialSize, finalSize) - require.Greater(t, finalSize, initialSize) -} - -func TestQlogCompression(t *testing.T) { - qlogDir := t.TempDir() - logger := newQlogger(qlogDir, logging.PerspectiveServer, quic.ConnectionIDFromBytes([]byte("connid"))) - logger.Write([]byte("foobar")) - require.NoError(t, logger.Close()) - compressed, err := os.ReadFile(qlogDir + "/" + getFile(t, qlogDir).Name()) - require.NoError(t, err) - require.NotEqual(t, "foobar", compressed) - c, err := zstd.NewReader(bytes.NewReader(compressed)) - require.NoError(t, err) - data, err := io.ReadAll(c) - require.NoError(t, err) - require.Equal(t, []byte("foobar"), data) -} diff --git a/p2p/transport/webrtc/logger.go b/p2p/transport/webrtc/logger.go index e2d1aabb8..d9a8f6f35 100644 --- a/p2p/transport/webrtc/logger.go +++ b/p2p/transport/webrtc/logger.go @@ -14,10 +14,11 @@ var log = logging.Logger("webrtc-transport") // pionLog is the logger provided to pion for internal logging var pionLog = logging.Logger("webrtc-transport-pion") -// pionLogger wraps the StandardLogger interface to provide a LeveledLogger interface -// as expected by pion -// Pion logs are too noisy and have invalid log levels. pionLogger downgrades all the -// logs to debug +// pionLogger adapts pion's logger to go-libp2p's semantics. +// Pion logs routine connection events (client disconnects, protocol mismatches, +// state races) as ERROR/WARN, but these are normal operational noise from a +// service perspective. We downgrade all pion logs to DEBUG to prevent log spam +// while preserving debuggability when needed. type pionLogger struct { *slog.Logger } @@ -37,32 +38,32 @@ func (l pionLogger) Debugf(s string, args ...interface{}) { } func (l pionLogger) Error(s string) { - l.Logger.Error(s) + l.Logger.Debug(s) } func (l pionLogger) Errorf(s string, args ...interface{}) { - if l.Logger.Enabled(context.Background(), slog.LevelError) { - l.Logger.Error(fmt.Sprintf(s, args...)) + if l.Logger.Enabled(context.Background(), slog.LevelDebug) { + l.Logger.Debug(fmt.Sprintf(s, args...)) } } func (l pionLogger) Info(s string) { - l.Logger.Info(s) + l.Logger.Debug(s) } func (l pionLogger) Infof(s string, args ...interface{}) { - if l.Logger.Enabled(context.Background(), slog.LevelInfo) { - l.Logger.Info(fmt.Sprintf(s, args...)) + if l.Logger.Enabled(context.Background(), slog.LevelDebug) { + l.Logger.Debug(fmt.Sprintf(s, args...)) } } func (l pionLogger) Warn(s string) { - l.Logger.Warn(s) + l.Logger.Debug(s) } func (l pionLogger) Warnf(s string, args ...interface{}) { - if l.Logger.Enabled(context.Background(), slog.LevelWarn) { - l.Logger.Warn(fmt.Sprintf(s, args...)) + if l.Logger.Enabled(context.Background(), slog.LevelDebug) { + l.Logger.Debug(fmt.Sprintf(s, args...)) } } diff --git a/p2p/transport/websocket/listener.go b/p2p/transport/websocket/listener.go index 7de1f42cf..45cfcfa22 100644 --- a/p2p/transport/websocket/listener.go +++ b/p2p/transport/websocket/listener.go @@ -126,8 +126,10 @@ func newListener(a ma.Multiaddr, tlsConf *tls.Config, sharedTcp *tcpreuse.ConnMg }, } ln.server = http.Server{ - Handler: ln, - ErrorLog: slog.NewLogLogger(log.Handler(), slog.LevelError), + Handler: ln, + // Use LevelDebug for http.Server errors (TLS handshake failures, connection issues). + // These are operational noise from misbehaving/buggy remote clients, not server errors. + ErrorLog: slog.NewLogLogger(log.Handler(), slog.LevelDebug), ConnContext: ln.ConnContext, TLSConfig: tlsConf, } diff --git a/p2p/transport/webtransport/listener.go b/p2p/transport/webtransport/listener.go index 7cd647f72..605586295 100644 --- a/p2p/transport/webtransport/listener.go +++ b/p2p/transport/webtransport/listener.go @@ -64,10 +64,11 @@ func newListener(reuseListener quicreuse.Listener, t *transport, isStaticTLSConf addr: reuseListener.Addr(), multiaddr: localMultiaddr, server: webtransport.Server{ - H3: http3.Server{ + H3: &http3.Server{ ConnContext: func(ctx context.Context, c *quic.Conn) context.Context { return context.WithValue(ctx, connKey{}, c) }, + EnableDatagrams: true, }, CheckOrigin: func(_ *http.Request) bool { return true }, }, @@ -77,6 +78,7 @@ func newListener(reuseListener quicreuse.Listener, t *transport, isStaticTLSConf mux := http.NewServeMux() mux.HandleFunc(webtransportHTTPEndpoint, ln.httpHandler) ln.server.H3.Handler = mux + webtransport.ConfigureHTTP3Server(ln.server.H3) go func() { defer close(ln.serverClosed) for { diff --git a/test-plans/go.mod b/test-plans/go.mod index 29e3819b6..80b6c6ba1 100644 --- a/test-plans/go.mod +++ b/test-plans/go.mod @@ -15,22 +15,21 @@ require ( github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dunglas/httpsfv v1.1.0 // indirect github.com/flynn/noise v1.1.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/ipfs/go-cid v0.5.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/koron/go-ssdp v0.0.6 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-flow-metrics v0.2.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-netroute v0.3.0 // indirect + github.com/libp2p/go-netroute v0.4.0 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-yamux/v5 v5.0.1 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect @@ -74,9 +73,9 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.64.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect - github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.55.0 // indirect - github.com/quic-go/webtransport-go v0.9.0 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/webtransport-go v0.10.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/wlynxg/anet v0.0.5 // indirect go.uber.org/dig v1.19.0 // indirect diff --git a/test-plans/go.sum b/test-plans/go.sum index f0112d835..e79dfab11 100644 --- a/test-plans/go.sum +++ b/test-plans/go.sum @@ -1,25 +1,9 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -31,44 +15,20 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvw github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/dunglas/httpsfv v1.1.0 h1:Jw76nAyKWKZKFrpMMcL76y35tOpYHqQPzHQiwDvpe54= +github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -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/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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= @@ -77,22 +37,14 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU= github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -106,20 +58,16 @@ github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUI github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-netroute v0.3.0 h1:nqPCXHmeNmgTJnktosJ/sIef9hvwYCrsLxXmfNks/oc= -github.com/libp2p/go-netroute v0.3.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= +github.com/libp2p/go-netroute v0.4.0 h1:sZZx9hyANYUx9PZyqcgE/E1GUG3iEtTZHUEvdtXT7/Q= +github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= 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/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg= github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marcopolo/simnet v0.0.1 h1:rSMslhPz6q9IvJeFWDoMGxMIrlsbXau3NkuIXHGJxfg= -github.com/marcopolo/simnet v0.0.1/go.mod h1:WDaQkgLAjqDUEBAOXz22+1j6wXKfGlC5sD5XWt3ddOs= +github.com/marcopolo/simnet v0.0.4 h1:50Kx4hS9kFGSRIbrt9xUS3NJX33EyPqHVmpXvaKLqrY= +github.com/marcopolo/simnet v0.0.4/go.mod h1:tfQF1u2DmaB6WHODMtQaLtClEf3a296CKQLq5gAsIS0= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= @@ -132,8 +80,6 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8Rv github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= @@ -161,15 +107,12 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= @@ -214,75 +157,39 @@ github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= -github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= -github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70= -github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/webtransport-go v0.10.0 h1:LqXXPOXuETY5Xe8ITdGisBzTYmUOy5eSj+9n4hLTjHI= +github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg= @@ -295,11 +202,7 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -309,24 +212,12 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 h1:bsqhLWFR6G6xiQcb+JoGqdKdRU6WzPWmK8E0jxTjzo4= golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -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= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= -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= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -339,26 +230,13 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -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= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -380,7 +258,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -389,55 +266,24 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/version.json b/version.json index 823117cc5..e5d29a373 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "v0.44.0" + "version": "v0.47.0" } diff --git a/x/simlibp2p/libp2p.go b/x/simlibp2p/libp2p.go index 47e745bb3..873526eff 100644 --- a/x/simlibp2p/libp2p.go +++ b/x/simlibp2p/libp2p.go @@ -1,6 +1,7 @@ -package simconnlibp2p +package simlibp2p import ( + "context" "crypto/rand" "fmt" "net" @@ -206,8 +207,12 @@ type NetworkSettings struct { BlankHostOptsForHostIdx func(idx int) BlankHostOpts } -func SimpleLibp2pNetwork(linkSettings []NodeLinkSettingsAndCount, networkSettings NetworkSettings) (*simnet.Simnet, *SimpleLibp2pNetworkMeta, error) { - nw := &simnet.Simnet{} +type LatencyFunc func(*simnet.Packet) time.Duration + +func SimpleLibp2pNetwork(linkSettings []NodeLinkSettingsAndCount, latencyFunc LatencyFunc, networkSettings NetworkSettings) (*simnet.Simnet, *SimpleLibp2pNetworkMeta, error) { + nw := &simnet.Simnet{ + LatencyFunc: latencyFunc, + } meta := &SimpleLibp2pNetworkMeta{ AddrToNode: make(map[string]HostAndIdx), } @@ -256,3 +261,28 @@ func SimpleLibp2pNetwork(linkSettings []NodeLinkSettingsAndCount, networkSetting return nw, meta, nil } + +// GetBasicHostPair gets a new pair of hosts. +// The first host initiates the connection to the second host. +func GetBasicHostPair(t *testing.T) (host.Host, host.Host) { + network, meta, err := SimpleLibp2pNetwork([]NodeLinkSettingsAndCount{{ + LinkSettings: simnet.NodeBiDiLinkSettings{ + Downlink: simnet.LinkSettings{BitsPerSecond: 20 * OneMbps}, + Uplink: simnet.LinkSettings{BitsPerSecond: 20 * OneMbps}, + }, Count: 2}, + }, simnet.StaticLatency(100/2*time.Millisecond), NetworkSettings{}) + require.NoError(t, err) + network.Start() + t.Cleanup(func() { + network.Close() + }) + + h1 := meta.Nodes[0] + h2 := meta.Nodes[1] + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + h2pi := h2.Peerstore().PeerInfo(h2.ID()) + require.NoError(t, h1.Connect(ctx, h2pi)) + return h1, h2 +} diff --git a/x/simlibp2p/synctest_test.go b/x/simlibp2p/synctest_test.go index 691c517dc..cb0ffa340 100644 --- a/x/simlibp2p/synctest_test.go +++ b/x/simlibp2p/synctest_test.go @@ -1,6 +1,6 @@ -//go:build goexperiment.synctest +//go:build go1.25 -package simconnlibp2p_test +package simlibp2p_test import ( "context" @@ -13,20 +13,20 @@ import ( "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/protocol/ping" - simlibp2p "github.com/libp2p/go-libp2p/x/simlibp2p" + "github.com/libp2p/go-libp2p/x/simlibp2p" "github.com/marcopolo/simnet" "github.com/stretchr/testify/require" ) func TestSimpleLibp2pNetwork_synctest(t *testing.T) { - synctest.Run(func() { + synctest.Test(t, func(t *testing.T) { latency := 10 * time.Millisecond network, meta, err := simlibp2p.SimpleLibp2pNetwork([]simlibp2p.NodeLinkSettingsAndCount{ {LinkSettings: simnet.NodeBiDiLinkSettings{ - Downlink: simnet.LinkSettings{BitsPerSecond: 20 * simlibp2p.OneMbps, Latency: latency / 2}, // Divide by two since this is latency for each direction - Uplink: simnet.LinkSettings{BitsPerSecond: 20 * simlibp2p.OneMbps, Latency: latency / 2}, + Downlink: simnet.LinkSettings{BitsPerSecond: 20 * simlibp2p.OneMbps}, // Divide by two since this is latency for each direction + Uplink: simnet.LinkSettings{BitsPerSecond: 20 * simlibp2p.OneMbps}, }, Count: 100}, - }, simlibp2p.NetworkSettings{}) + }, simnet.StaticLatency(latency/2), simlibp2p.NetworkSettings{}) require.NoError(t, err) network.Start() defer network.Close() @@ -74,19 +74,17 @@ func TestSimpleLibp2pNetwork_synctest(t *testing.T) { } func TestSimpleSimNetPing_synctest(t *testing.T) { - synctest.Run(func() { - router := &simnet.Simnet{} + synctest.Test(t, func(t *testing.T) { + const latency = 10 * time.Millisecond + router := &simnet.Simnet{LatencyFunc: simnet.StaticLatency(latency / 2)} const bandwidth = 10 * simlibp2p.OneMbps - const latency = 10 * time.Millisecond linkSettings := simnet.NodeBiDiLinkSettings{ Downlink: simnet.LinkSettings{ BitsPerSecond: bandwidth, - Latency: latency / 2, }, Uplink: simnet.LinkSettings{ BitsPerSecond: bandwidth, - Latency: latency / 2, }, } @@ -101,14 +99,13 @@ func TestSimpleSimNetPing_synctest(t *testing.T) { simlibp2p.QUICSimnet(router, linkSettings), ) - err := router.Start() - require.NoError(t, err) + router.Start() defer router.Close() defer hostA.Close() defer hostB.Close() - err = hostA.Connect(context.Background(), peer.AddrInfo{ + err := hostA.Connect(context.Background(), peer.AddrInfo{ ID: hostB.ID(), Addrs: hostB.Addrs(), })