From 8a5068e85b794ebafaac3d05f2a2fd1bb0d242de Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:32:03 -0700 Subject: [PATCH 01/13] feat(peers): add verifypeer module with ParsePeer Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/verifypeer/go.mod | 91 ++++++ scripts/peers/verifypeer/go.sum | 359 ++++++++++++++++++++++++ scripts/peers/verifypeer/verify.go | 27 ++ scripts/peers/verifypeer/verify_test.go | 34 +++ 4 files changed, 511 insertions(+) create mode 100644 scripts/peers/verifypeer/go.mod create mode 100644 scripts/peers/verifypeer/go.sum create mode 100644 scripts/peers/verifypeer/verify.go create mode 100644 scripts/peers/verifypeer/verify_test.go diff --git a/scripts/peers/verifypeer/go.mod b/scripts/peers/verifypeer/go.mod new file mode 100644 index 00000000..414a54ca --- /dev/null +++ b/scripts/peers/verifypeer/go.mod @@ -0,0 +1,91 @@ +module github.com/celestiaorg/networks/scripts/peers/verifypeer + +go 1.26.1 + +replace github.com/cometbft/cometbft => github.com/celestiaorg/celestia-core v0.40.2 + +require github.com/cometbft/cometbft v0.0.0-00010101000000-000000000000 + +require ( + github.com/DataDog/zstd v1.5.6 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.13 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect + github.com/aws/smithy-go v1.24.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/celestiaorg/go-square/v3 v3.0.2 // indirect + github.com/celestiaorg/nmt v0.24.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 // indirect + github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect + github.com/cockroachdb/pebble v1.1.4 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft-db v1.0.4 // indirect + github.com/cosmos/gogoproto v1.7.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/dgraph-io/badger/v4 v4.5.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/getsentry/sentry-go v0.31.1 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/flatbuffers v25.1.24+incompatible // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/klauspost/reedsolomon v1.13.3 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/linxGnu/grocksdb v1.9.8 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae // indirect + github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/sasha-s/go-deadlock v0.3.9 // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + go.etcd.io/bbolt v1.4.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/grpc v1.79.3 // indirect + google.golang.org/protobuf v1.36.11 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/scripts/peers/verifypeer/go.sum b/scripts/peers/verifypeer/go.sum new file mode 100644 index 00000000..7b2c823f --- /dev/null +++ b/scripts/peers/verifypeer/go.sum @@ -0,0 +1,359 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= +github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= +github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= +github.com/aws/aws-sdk-go-v2/config v1.32.13 h1:5KgbxMaS2coSWRrx9TX/QtWbqzgQkOdEa3sZPhBhCSg= +github.com/aws/aws-sdk-go-v2/config v1.32.13/go.mod h1:8zz7wedqtCbw5e9Mi2doEwDyEgHcEE9YOJp6a8jdSMY= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI= +github.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +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/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/celestiaorg/celestia-core v0.40.2 h1:+8D3anWx0mn0Wyp/Hahml/1ZiyDc5yGbIR/k4iFtqms= +github.com/celestiaorg/celestia-core v0.40.2/go.mod h1:ZCrmRE1UQzgZfho4Og6tAHtH1KY6s8Jpri5+EKobV5c= +github.com/celestiaorg/go-square/v3 v3.0.2 h1:eSQOgNII8inK9IhiBZ+6GADQeWbRq4HYY72BOgcduA4= +github.com/celestiaorg/go-square/v3 v3.0.2/go.mod h1:oFReMLsSDMRs82ICFEeFQFCqNvwdsbIM1BzCcb0f7dM= +github.com/celestiaorg/nmt v0.24.2 h1:LlpJSPOd6/Lw1Ig6HUhZuqiINHLka/ZSRTBzlNJpchg= +github.com/celestiaorg/nmt v0.24.2/go.mod h1:vgLBpWBi8F5KLxTdXSwb7AU4NhiIQ1AQRGa+PzdcLEA= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0 h1:pU88SPhIFid6/k0egdR5V6eALQYq2qbSmukrkgIh/0A= +github.com/cockroachdb/fifo v0.0.0-20240816210425-c5d0cb0b6fc0/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 h1:ASDL+UJcILMqgNeV5jiqR4j+sTuvQNHdf2chuKj1M5k= +github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506/go.mod h1:Mw7HqKr2kdtu6aYGn3tPmAftiP3QPX63LdK/zcariIo= +github.com/cockroachdb/pebble v1.1.4 h1:5II1uEP4MyHLDnsrbv/EZ36arcb9Mxg3n+owhZ3GrG8= +github.com/cockroachdb/pebble v1.1.4/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cometbft/cometbft-db v1.0.4 h1:cezb8yx/ZWcF124wqUtAFjAuDksS1y1yXedvtprUFxs= +github.com/cometbft/cometbft-db v1.0.4/go.mod h1:M+BtHAGU2XLrpUxo3Nn1nOCcnVCiLM9yx5OuT0u5SCA= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/getsentry/sentry-go v0.31.1 h1:ELVc0h7gwyhnXHDouXkhqTFSO5oslsRDk0++eyE0KJ4= +github.com/getsentry/sentry-go v0.31.1/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v25.1.24+incompatible h1:4wPqL3K7GzBd1CwyhSd3usxLKOaJN/AC6puCca6Jm7o= +github.com/google/flatbuffers v25.1.24+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +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.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/reedsolomon v1.13.3 h1:01GwnO2xoCSaM0ShP4qwl+FsHg3csFShC6Tu/RS1ji0= +github.com/klauspost/reedsolomon v1.13.3/go.mod h1:yjqqjgMTQkBUHSG97/rm4zipffCNbCiZcB3kTqr++sQ= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= +github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= +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/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae h1:FatpGJD2jmJfhZiFDElaC0QhZUDQnxUeAwTGkfAHN3I= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe h1:vHpqOnPlnkba8iSxU4j/CvDSS9J4+F4473esQsYLGoE= +github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w= +github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y= +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.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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +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/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= +go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= +google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/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= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/scripts/peers/verifypeer/verify.go b/scripts/peers/verifypeer/verify.go new file mode 100644 index 00000000..49e9c838 --- /dev/null +++ b/scripts/peers/verifypeer/verify.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/cometbft/cometbft/p2p" +) + +// ParsePeer splits an "id@host:port" line into a lowercased node ID and a +// dial address. The ID must be 40 hex characters (a 20-byte CometBFT node ID). +func ParsePeer(line string) (id p2p.ID, dialAddr string, err error) { + line = strings.TrimSpace(line) + at := strings.IndexByte(line, '@') + if at < 0 { + return "", "", fmt.Errorf("missing '@' in peer %q", line) + } + rawID := strings.ToLower(line[:at]) + addr := line[at+1:] + if rawID == "" || addr == "" { + return "", "", fmt.Errorf("empty id or address in peer %q", line) + } + if len(rawID) != 40 { + return "", "", fmt.Errorf("id must be 40 hex chars, got %d in peer %q", len(rawID), line) + } + return p2p.ID(rawID), addr, nil +} diff --git a/scripts/peers/verifypeer/verify_test.go b/scripts/peers/verifypeer/verify_test.go new file mode 100644 index 00000000..fa9f2e71 --- /dev/null +++ b/scripts/peers/verifypeer/verify_test.go @@ -0,0 +1,34 @@ +package main + +import "testing" + +func TestParsePeer(t *testing.T) { + tests := []struct { + name string + line string + wantID string + wantAddr string + wantErr bool + }{ + {"valid", "13612522d3ce71a181881370b8f40103d4def9f1@84.32.32.148:16400", "13612522d3ce71a181881370b8f40103d4def9f1", "84.32.32.148:16400", false}, + {"uppercase id lowercased", "13612522D3CE71A181881370B8F40103D4DEF9F1@1.2.3.4:26656", "13612522d3ce71a181881370b8f40103d4def9f1", "1.2.3.4:26656", false}, + {"missing @", "13612522d3ce71a181881370b8f40103d4def9f1-1.2.3.4:26656", "", "", true}, + {"empty id", "@1.2.3.4:26656", "", "", true}, + {"empty addr", "13612522d3ce71a181881370b8f40103d4def9f1@", "", "", true}, + {"short id", "abc@1.2.3.4:26656", "", "", true}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + id, addr, err := ParsePeer(tc.line) + if (err != nil) != tc.wantErr { + t.Fatalf("err = %v, wantErr %v", err, tc.wantErr) + } + if tc.wantErr { + return + } + if string(id) != tc.wantID || addr != tc.wantAddr { + t.Fatalf("got (%q, %q), want (%q, %q)", id, addr, tc.wantID, tc.wantAddr) + } + }) + } +} From e4f425c4157fdf5072149dcf61ec22285856febe Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:34:54 -0700 Subject: [PATCH 02/13] refactor(peers): validate node ID is hex; expand ParsePeer tests Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/verifypeer/verify.go | 5 +++++ scripts/peers/verifypeer/verify_test.go | 3 +++ 2 files changed, 8 insertions(+) diff --git a/scripts/peers/verifypeer/verify.go b/scripts/peers/verifypeer/verify.go index 49e9c838..288ac908 100644 --- a/scripts/peers/verifypeer/verify.go +++ b/scripts/peers/verifypeer/verify.go @@ -1,6 +1,7 @@ package main import ( + "encoding/hex" "fmt" "strings" @@ -9,6 +10,7 @@ import ( // ParsePeer splits an "id@host:port" line into a lowercased node ID and a // dial address. The ID must be 40 hex characters (a 20-byte CometBFT node ID). +// The returned dial address is not validated here; validation happens at dial time. func ParsePeer(line string) (id p2p.ID, dialAddr string, err error) { line = strings.TrimSpace(line) at := strings.IndexByte(line, '@') @@ -23,5 +25,8 @@ func ParsePeer(line string) (id p2p.ID, dialAddr string, err error) { if len(rawID) != 40 { return "", "", fmt.Errorf("id must be 40 hex chars, got %d in peer %q", len(rawID), line) } + if _, err := hex.DecodeString(rawID); err != nil { + return "", "", fmt.Errorf("id must be hex in peer %q: %w", line, err) + } return p2p.ID(rawID), addr, nil } diff --git a/scripts/peers/verifypeer/verify_test.go b/scripts/peers/verifypeer/verify_test.go index fa9f2e71..7fed7408 100644 --- a/scripts/peers/verifypeer/verify_test.go +++ b/scripts/peers/verifypeer/verify_test.go @@ -16,6 +16,9 @@ func TestParsePeer(t *testing.T) { {"empty id", "@1.2.3.4:26656", "", "", true}, {"empty addr", "13612522d3ce71a181881370b8f40103d4def9f1@", "", "", true}, {"short id", "abc@1.2.3.4:26656", "", "", true}, + {"leading/trailing whitespace trimmed", " 13612522d3ce71a181881370b8f40103d4def9f1@1.2.3.4:26656\n", "13612522d3ce71a181881370b8f40103d4def9f1", "1.2.3.4:26656", false}, + {"long id (41 hex chars)", "13612522d3ce71a181881370b8f40103d4def9f1a@1.2.3.4:26656", "", "", true}, + {"non-hex id (40 chars with z)", "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz@1.2.3.4:26656", "", "", true}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { From dd4b4e9ea08f1cdf4fb5b2518c1ddb7d7504f898 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:37:04 -0700 Subject: [PATCH 03/13] feat(peers): verify peer node ID via secret-connection handshake Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/verifypeer/verify.go | 56 ++++++++++++++++++++ scripts/peers/verifypeer/verify_test.go | 68 ++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/scripts/peers/verifypeer/verify.go b/scripts/peers/verifypeer/verify.go index 288ac908..5bdf0fda 100644 --- a/scripts/peers/verifypeer/verify.go +++ b/scripts/peers/verifypeer/verify.go @@ -3,9 +3,13 @@ package main import ( "encoding/hex" "fmt" + "net" "strings" + "time" + "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/p2p" + "github.com/cometbft/cometbft/p2p/conn" ) // ParsePeer splits an "id@host:port" line into a lowercased node ID and a @@ -30,3 +34,55 @@ func ParsePeer(line string) (id p2p.ID, dialAddr string, err error) { } return p2p.ID(rawID), addr, nil } + +type Status string + +const ( + StatusVerified Status = "verified" + StatusIDMismatch Status = "id_mismatch" + StatusUnreachable Status = "unreachable" + StatusInvalid Status = "invalid" +) + +type Result struct { + Line string `json:"line"` + ClaimedID string `json:"claimed_id"` + RemoteID string `json:"remote_id,omitempty"` + Status Status `json:"status"` + Err string `json:"error,omitempty"` +} + +// VerifyPeer dials the peer, performs the CometBFT secret-connection handshake, +// and confirms the authenticated remote node ID equals the claimed id@. +func VerifyPeer(line string, timeout time.Duration) Result { + claimedID, dialAddr, err := ParsePeer(line) + if err != nil { + return Result{Line: line, Status: StatusInvalid, Err: err.Error()} + } + res := Result{Line: line, ClaimedID: string(claimedID)} + + d := net.Dialer{Timeout: timeout} + c, err := d.Dial("tcp", dialAddr) + if err != nil { + res.Status = StatusUnreachable + res.Err = err.Error() + return res + } + defer c.Close() + _ = c.SetDeadline(time.Now().Add(timeout)) + + sc, err := conn.MakeSecretConnection(c, ed25519.GenPrivKey()) + if err != nil { + res.Status = StatusUnreachable + res.Err = "handshake: " + err.Error() + return res + } + remoteID := p2p.PubKeyToID(sc.RemotePubKey()) + res.RemoteID = string(remoteID) + if !strings.EqualFold(string(remoteID), string(claimedID)) { + res.Status = StatusIDMismatch + return res + } + res.Status = StatusVerified + return res +} diff --git a/scripts/peers/verifypeer/verify_test.go b/scripts/peers/verifypeer/verify_test.go index 7fed7408..711eb344 100644 --- a/scripts/peers/verifypeer/verify_test.go +++ b/scripts/peers/verifypeer/verify_test.go @@ -1,6 +1,14 @@ package main -import "testing" +import ( + "net" + "testing" + "time" + + "github.com/cometbft/cometbft/crypto/ed25519" + "github.com/cometbft/cometbft/p2p" + "github.com/cometbft/cometbft/p2p/conn" +) func TestParsePeer(t *testing.T) { tests := []struct { @@ -35,3 +43,61 @@ func TestParsePeer(t *testing.T) { }) } } + +// startHandshakeServer accepts one connection, performs the server side of the +// secret-connection handshake using serverKey, then closes. Returns the +// listener address and the server's node ID. +func startHandshakeServer(t *testing.T, serverKey ed25519.PrivKey) (addr string, nodeID p2p.ID) { + t.Helper() + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = ln.Close() }) + go func() { + c, err := ln.Accept() + if err != nil { + return + } + defer c.Close() + _ = c.SetDeadline(time.Now().Add(3 * time.Second)) + // Server side of the handshake. Result is discarded; we only need the + // dialer to complete its side. + _, _ = conn.MakeSecretConnection(c, serverKey) + }() + return ln.Addr().String(), p2p.PubKeyToID(serverKey.PubKey()) +} + +func TestVerifyPeer_Match(t *testing.T) { + key := ed25519.GenPrivKey() + addr, id := startHandshakeServer(t, key) + res := VerifyPeer(string(id)+"@"+addr, 3*time.Second) + if res.Status != StatusVerified { + t.Fatalf("status = %q (%s), want verified", res.Status, res.Err) + } + if res.RemoteID != string(id) { + t.Fatalf("remoteID = %q, want %q", res.RemoteID, id) + } +} + +func TestVerifyPeer_Mismatch(t *testing.T) { + key := ed25519.GenPrivKey() + addr, _ := startHandshakeServer(t, key) + wrongID := "0000000000000000000000000000000000000000" + res := VerifyPeer(wrongID+"@"+addr, 3*time.Second) + if res.Status != StatusIDMismatch { + t.Fatalf("status = %q, want id_mismatch", res.Status) + } +} + +func TestVerifyPeer_Unreachable(t *testing.T) { + // Reserve a port then close it so the dial is refused/times out. + ln, _ := net.Listen("tcp", "127.0.0.1:0") + addr := ln.Addr().String() + _ = ln.Close() + id := "1111111111111111111111111111111111111111" + res := VerifyPeer(id+"@"+addr, 1*time.Second) + if res.Status != StatusUnreachable { + t.Fatalf("status = %q, want unreachable", res.Status) + } +} From 5f255aa6f51fe4aab6c9105fccacad658ba23051 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:39:45 -0700 Subject: [PATCH 04/13] test(peers): check listen error in unreachable test; clarify VerifyPeer comments --- scripts/peers/verifypeer/verify.go | 2 ++ scripts/peers/verifypeer/verify_test.go | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/peers/verifypeer/verify.go b/scripts/peers/verifypeer/verify.go index 5bdf0fda..629ff673 100644 --- a/scripts/peers/verifypeer/verify.go +++ b/scripts/peers/verifypeer/verify.go @@ -69,8 +69,10 @@ func VerifyPeer(line string, timeout time.Duration) Result { return res } defer c.Close() + // Deadline covers the handshake; total time may be up to ~2×timeout. _ = c.SetDeadline(time.Now().Add(timeout)) + // Use a one-time key; we only need to authenticate the remote peer, not ourselves. sc, err := conn.MakeSecretConnection(c, ed25519.GenPrivKey()) if err != nil { res.Status = StatusUnreachable diff --git a/scripts/peers/verifypeer/verify_test.go b/scripts/peers/verifypeer/verify_test.go index 711eb344..dde2edfa 100644 --- a/scripts/peers/verifypeer/verify_test.go +++ b/scripts/peers/verifypeer/verify_test.go @@ -91,8 +91,12 @@ func TestVerifyPeer_Mismatch(t *testing.T) { } func TestVerifyPeer_Unreachable(t *testing.T) { - // Reserve a port then close it so the dial is refused/times out. - ln, _ := net.Listen("tcp", "127.0.0.1:0") + // Reserve a loopback port then close it so the dial is refused. The brief + // reuse window is acceptable for this hermetic test. + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } addr := ln.Addr().String() _ = ln.Close() id := "1111111111111111111111111111111111111111" From bf7595bfd59ef33897ef9daaae73f95fc791f83a Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:41:58 -0700 Subject: [PATCH 05/13] feat(peers): verifypeer CLI with concurrency, min-count gate, JSON report Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/verifypeer/main.go | 127 ++++++++++++++++++++++++++ scripts/peers/verifypeer/main_test.go | 32 +++++++ 2 files changed, 159 insertions(+) create mode 100644 scripts/peers/verifypeer/main.go create mode 100644 scripts/peers/verifypeer/main_test.go diff --git a/scripts/peers/verifypeer/main.go b/scripts/peers/verifypeer/main.go new file mode 100644 index 00000000..0f850355 --- /dev/null +++ b/scripts/peers/verifypeer/main.go @@ -0,0 +1,127 @@ +package main + +import ( + "bufio" + "encoding/json" + "flag" + "fmt" + "os" + "sort" + "strings" + "sync" + "time" +) + +func verifiedLines(results []Result) []string { + var out []string + for _, r := range results { + if r.Status == StatusVerified { + out = append(out, r.Line) + } + } + return out +} + +func mismatches(results []Result) []Result { + var out []Result + for _, r := range results { + if r.Status == StatusIDMismatch { + out = append(out, r) + } + } + return out +} + +func readCandidates(path string) ([]string, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + var lines []string + sc := bufio.NewScanner(f) + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + if line != "" { + lines = append(lines, line) + } + } + return lines, sc.Err() +} + +// verifyAll runs VerifyPeer over candidates with bounded concurrency, +// preserving input order in the returned slice. +func verifyAll(candidates []string, concurrency int, timeout time.Duration) []Result { + results := make([]Result, len(candidates)) + sem := make(chan struct{}, concurrency) + var wg sync.WaitGroup + for i, line := range candidates { + wg.Add(1) + sem <- struct{}{} + go func(i int, line string) { + defer wg.Done() + defer func() { <-sem }() + results[i] = VerifyPeer(line, timeout) + }(i, line) + } + wg.Wait() + return results +} + +func main() { + in := flag.String("in", "", "input file of id@host:port candidate lines") + out := flag.String("out", "", "output file for verified peer lines") + report := flag.String("report", "", "output file for JSON verification report") + min := flag.Int("min", 8, "minimum verified peers required (else exit 1)") + concurrency := flag.Int("concurrency", 16, "max concurrent dials") + timeoutSec := flag.Int("timeout", 5, "per-peer dial+handshake timeout in seconds") + flag.Parse() + + if *in == "" || *out == "" { + fmt.Fprintln(os.Stderr, "usage: verifypeer -in candidates.txt -out peers.txt [-report report.json] [-min N]") + os.Exit(2) + } + + candidates, err := readCandidates(*in) + if err != nil { + fmt.Fprintf(os.Stderr, "read candidates: %v\n", err) + os.Exit(1) + } + + results := verifyAll(candidates, *concurrency, time.Duration(*timeoutSec)*time.Second) + verified := verifiedLines(results) + sort.Strings(verified) // deterministic output independent of dial timing + + if err := os.WriteFile(*out, []byte(strings.Join(verified, "\n")+"\n"), 0o644); err != nil { + fmt.Fprintf(os.Stderr, "write out: %v\n", err) + os.Exit(1) + } + + if *report != "" { + b, _ := json.MarshalIndent(results, "", " ") + _ = os.WriteFile(*report, b, 0o644) + } + + mm := mismatches(results) + fmt.Printf("candidates=%d verified=%d unreachable=%d id_mismatch=%d invalid=%d\n", + len(candidates), len(verified), + countStatus(results, StatusUnreachable), len(mm), countStatus(results, StatusInvalid)) + for _, r := range mm { + fmt.Fprintf(os.Stderr, "ID MISMATCH: claimed=%s remote=%s line=%s\n", r.ClaimedID, r.RemoteID, r.Line) + } + + if len(verified) < *min { + fmt.Fprintf(os.Stderr, "FAIL: only %d verified peers, need >= %d\n", len(verified), *min) + os.Exit(1) + } +} + +func countStatus(results []Result, s Status) int { + n := 0 + for _, r := range results { + if r.Status == s { + n++ + } + } + return n +} diff --git a/scripts/peers/verifypeer/main_test.go b/scripts/peers/verifypeer/main_test.go new file mode 100644 index 00000000..a4e34b21 --- /dev/null +++ b/scripts/peers/verifypeer/main_test.go @@ -0,0 +1,32 @@ +package main + +import "testing" + +func TestVerifiedLines(t *testing.T) { + results := []Result{ + {Line: "a@1:1", ClaimedID: "a", Status: StatusVerified}, + {Line: "b@2:2", ClaimedID: "b", Status: StatusUnreachable}, + {Line: "c@3:3", ClaimedID: "c", Status: StatusIDMismatch}, + {Line: "d@4:4", ClaimedID: "d", Status: StatusVerified}, + } + got := verifiedLines(results) + want := []string{"a@1:1", "d@4:4"} + if len(got) != len(want) { + t.Fatalf("got %v, want %v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("got %v, want %v", got, want) + } + } +} + +func TestMismatches(t *testing.T) { + results := []Result{ + {Line: "c@3:3", Status: StatusIDMismatch}, + {Line: "a@1:1", Status: StatusVerified}, + } + if n := len(mismatches(results)); n != 1 { + t.Fatalf("mismatches = %d, want 1", n) + } +} From 3bdaf0c83eff096dd485ff1e95c01e7e8e07148f Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:43:39 -0700 Subject: [PATCH 06/13] chore(peers): gitignore verifypeer build artifact --- scripts/peers/verifypeer/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 scripts/peers/verifypeer/.gitignore diff --git a/scripts/peers/verifypeer/.gitignore b/scripts/peers/verifypeer/.gitignore new file mode 100644 index 00000000..58c78d25 --- /dev/null +++ b/scripts/peers/verifypeer/.gitignore @@ -0,0 +1 @@ +/verifypeer From 48a98d4bda13ac3a36769715d3e3f98850304426 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:46:01 -0700 Subject: [PATCH 07/13] refactor(peers): warn on report write error; harden CLI output and tests Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/verifypeer/main.go | 12 ++++-- scripts/peers/verifypeer/main_test.go | 56 +++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/scripts/peers/verifypeer/main.go b/scripts/peers/verifypeer/main.go index 0f850355..079c3499 100644 --- a/scripts/peers/verifypeer/main.go +++ b/scripts/peers/verifypeer/main.go @@ -78,7 +78,7 @@ func main() { flag.Parse() if *in == "" || *out == "" { - fmt.Fprintln(os.Stderr, "usage: verifypeer -in candidates.txt -out peers.txt [-report report.json] [-min N]") + fmt.Fprintln(os.Stderr, "usage: verifypeer -in candidates.txt -out peers.txt [-report report.json] [-min N] [-concurrency N] [-timeout SECONDS]") os.Exit(2) } @@ -92,14 +92,20 @@ func main() { verified := verifiedLines(results) sort.Strings(verified) // deterministic output independent of dial timing - if err := os.WriteFile(*out, []byte(strings.Join(verified, "\n")+"\n"), 0o644); err != nil { + content := []byte{} + if len(verified) > 0 { + content = []byte(strings.Join(verified, "\n") + "\n") + } + if err := os.WriteFile(*out, content, 0o644); err != nil { fmt.Fprintf(os.Stderr, "write out: %v\n", err) os.Exit(1) } if *report != "" { b, _ := json.MarshalIndent(results, "", " ") - _ = os.WriteFile(*report, b, 0o644) + if err := os.WriteFile(*report, b, 0o644); err != nil { + fmt.Fprintf(os.Stderr, "write report: %v\n", err) + } } mm := mismatches(results) diff --git a/scripts/peers/verifypeer/main_test.go b/scripts/peers/verifypeer/main_test.go index a4e34b21..9a8a249d 100644 --- a/scripts/peers/verifypeer/main_test.go +++ b/scripts/peers/verifypeer/main_test.go @@ -1,6 +1,10 @@ package main -import "testing" +import ( + "os" + "testing" + "time" +) func TestVerifiedLines(t *testing.T) { results := []Result{ @@ -26,7 +30,53 @@ func TestMismatches(t *testing.T) { {Line: "c@3:3", Status: StatusIDMismatch}, {Line: "a@1:1", Status: StatusVerified}, } - if n := len(mismatches(results)); n != 1 { - t.Fatalf("mismatches = %d, want 1", n) + got := mismatches(results) + if len(got) != 1 { + t.Fatalf("mismatches = %d, want 1", len(got)) + } + if got[0].Line != "c@3:3" || got[0].Status != StatusIDMismatch { + t.Fatalf("got %+v, want the id_mismatch entry", got[0]) + } +} + +func TestReadCandidates(t *testing.T) { + dir := t.TempDir() + path := dir + "/cand.txt" + content := " a@1.2.3.4:26656 \n\n\nb@5.6.7.8:26656\n \n" + if err := os.WriteFile(path, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + got, err := readCandidates(path) + if err != nil { + t.Fatal(err) + } + want := []string{"a@1.2.3.4:26656", "b@5.6.7.8:26656"} + if len(got) != len(want) { + t.Fatalf("got %v, want %v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("got %v, want %v", got, want) + } + } +} + +func TestVerifyAll(t *testing.T) { + if got := verifyAll(nil, 4, time.Second); len(got) != 0 { + t.Fatalf("empty input: got %d results, want 0", len(got)) + } + // Invalid lines resolve to StatusInvalid without any network I/O. + in := []string{"not-a-peer-0", "not-a-peer-1", "not-a-peer-2"} + got := verifyAll(in, 2, time.Second) + if len(got) != len(in) { + t.Fatalf("got %d results, want %d", len(got), len(in)) + } + for i := range in { + if got[i].Line != in[i] { + t.Fatalf("order not preserved at %d: got %q want %q", i, got[i].Line, in[i]) + } + if got[i].Status != StatusInvalid { + t.Fatalf("line %q: status %q, want invalid", in[i], got[i].Status) + } } } From 0d868e109028d4118493ef668ad04e667cb14ba4 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:47:35 -0700 Subject: [PATCH 08/13] feat(peers): add fetch-filter.sh with golden dry-run test Co-Authored-By: Claude Sonnet 4.6 --- scripts/peers/fetch-filter.bats | 9 +++++++++ scripts/peers/fetch-filter.sh | 21 +++++++++++++++++++++ scripts/peers/testdata/peers.sample.golden | 2 ++ scripts/peers/testdata/peers.sample.json | 10 ++++++++++ 4 files changed, 42 insertions(+) create mode 100644 scripts/peers/fetch-filter.bats create mode 100755 scripts/peers/fetch-filter.sh create mode 100644 scripts/peers/testdata/peers.sample.golden create mode 100644 scripts/peers/testdata/peers.sample.json diff --git a/scripts/peers/fetch-filter.bats b/scripts/peers/fetch-filter.bats new file mode 100644 index 00000000..fe3bb63d --- /dev/null +++ b/scripts/peers/fetch-filter.bats @@ -0,0 +1,9 @@ +#!/usr/bin/env bats + +@test "dry-run filters tcp_verified and sorts by score desc" { + run bash "$BATS_TEST_DIRNAME/fetch-filter.sh" --dry-run \ + "$BATS_TEST_DIRNAME/testdata/peers.sample.json" /tmp/cand_out.txt + [ "$status" -eq 0 ] + run diff -u "$BATS_TEST_DIRNAME/testdata/peers.sample.golden" /tmp/cand_out.txt + [ "$status" -eq 0 ] +} diff --git a/scripts/peers/fetch-filter.sh b/scripts/peers/fetch-filter.sh new file mode 100755 index 00000000..fd5fe1e3 --- /dev/null +++ b/scripts/peers/fetch-filter.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Fetch the Cumulo peer feed (or read a local fixture) and emit candidate +# "id@host:port" lines: tcp_verified peers, sorted by score descending. +# +# Usage: +# fetch-filter.sh +# fetch-filter.sh --dry-run +set -euo pipefail + +FILTER='.peers | sort_by(.score) | reverse | .[] | select(.tcp_verified == true) | .connection_string' + +if [[ "${1:-}" == "--dry-run" ]]; then + fixture="${2:?fixture path required}" + out="${3:?out file required}" + jq -r "$FILTER" "$fixture" > "$out" + exit 0 +fi + +url="${1:?cumulo url required}" +out="${2:?out file required}" +curl -fsSL "$url" | jq -r "$FILTER" > "$out" diff --git a/scripts/peers/testdata/peers.sample.golden b/scripts/peers/testdata/peers.sample.golden new file mode 100644 index 00000000..1eaf9c67 --- /dev/null +++ b/scripts/peers/testdata/peers.sample.golden @@ -0,0 +1,2 @@ +13612522d3ce71a181881370b8f40103d4def9f1@84.32.32.148:16400 +213f44afb503be593a1c8eb27dae86a50363e500@65.109.93.17:11656 diff --git a/scripts/peers/testdata/peers.sample.json b/scripts/peers/testdata/peers.sample.json new file mode 100644 index 00000000..943710dc --- /dev/null +++ b/scripts/peers/testdata/peers.sample.json @@ -0,0 +1,10 @@ +{ + "chain_id": "celestia", + "network": "mainnet", + "peer_count": 3, + "peers": [ + { "connection_string": "13612522d3ce71a181881370b8f40103d4def9f1@84.32.32.148:16400", "score": 2.1, "tcp_verified": true }, + { "connection_string": "213f44afb503be593a1c8eb27dae86a50363e500@65.109.93.17:11656", "score": 1.5, "tcp_verified": true }, + { "connection_string": "deadbeef00000000000000000000000000000000@10.0.0.1:26656", "score": 9.9, "tcp_verified": false } + ] +} From 2c4888fbf399503de4cf93de074838b3129faa11 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:49:17 -0700 Subject: [PATCH 09/13] test(peers): use per-test tmpdir in fetch-filter bats test --- scripts/peers/fetch-filter.bats | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/peers/fetch-filter.bats b/scripts/peers/fetch-filter.bats index fe3bb63d..131787ed 100644 --- a/scripts/peers/fetch-filter.bats +++ b/scripts/peers/fetch-filter.bats @@ -1,9 +1,10 @@ #!/usr/bin/env bats @test "dry-run filters tcp_verified and sorts by score desc" { + out="$BATS_TEST_TMPDIR/cand_out.txt" run bash "$BATS_TEST_DIRNAME/fetch-filter.sh" --dry-run \ - "$BATS_TEST_DIRNAME/testdata/peers.sample.json" /tmp/cand_out.txt + "$BATS_TEST_DIRNAME/testdata/peers.sample.json" "$out" [ "$status" -eq 0 ] - run diff -u "$BATS_TEST_DIRNAME/testdata/peers.sample.golden" /tmp/cand_out.txt + run diff -u "$BATS_TEST_DIRNAME/testdata/peers.sample.golden" "$out" [ "$status" -eq 0 ] } From 3287ee2fe187cfd7ec19e303f589ca513fc4c0e3 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:51:01 -0700 Subject: [PATCH 10/13] ci(peers): weekly workflow to refresh peers.txt + addrbook.json --- .github/workflows/update-peers.yml | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 .github/workflows/update-peers.yml diff --git a/.github/workflows/update-peers.yml b/.github/workflows/update-peers.yml new file mode 100644 index 00000000..8d6c66de --- /dev/null +++ b/.github/workflows/update-peers.yml @@ -0,0 +1,104 @@ +name: Update peers + +on: + schedule: + - cron: "0 0 * * 1" # Mondays 00:00 UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +env: + CELESTIA_APP_VERSION: v8.0.3 # bump to pull a newer addrbook generator + MIN_PEERS: "8" + CHURN_WARN_PCT: "60" + +jobs: + update: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: mainnet + url: https://peers.cumulo.me/peers/celestia/mainnet/peers.json + dir: celestia + - name: mocha-4 + url: https://peers.cumulo.me/peers/celestia/testnet/peers.json + dir: mocha-4 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: scripts/peers/verifypeer/go.mod + + - name: Install jq + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Fetch + filter candidates + run: | + ./scripts/peers/fetch-filter.sh "${{ matrix.url }}" /tmp/candidates.txt + echo "Candidates: $(wc -l < /tmp/candidates.txt)" + + - name: Verify peers (handshake + ID match) + working-directory: scripts/peers/verifypeer + run: | + go run . \ + -in /tmp/candidates.txt \ + -out "${GITHUB_WORKSPACE}/${{ matrix.dir }}/peers.txt" \ + -report /tmp/report.json \ + -min "${MIN_PEERS}" + + - name: Generate addrbook.json + run: | + asset="celestia-app-standalone_Linux_x86_64.tar.gz" + curl -fsSL -o /tmp/app.tar.gz \ + "https://github.com/celestiaorg/celestia-app/releases/download/${CELESTIA_APP_VERSION}/${asset}" + tar -xzf /tmp/app.tar.gz -C /tmp celestia-appd + /tmp/celestia-appd addrbook "${{ matrix.dir }}/peers.txt" "${{ matrix.dir }}/addrbook.json" + + - name: Compute churn + build PR body + id: meta + run: | + mismatch_count=$(jq '[.[] | select(.status=="id_mismatch")] | length' /tmp/report.json) + verified=$(wc -l < "${{ matrix.dir }}/peers.txt") + { + echo "### ${{ matrix.name }} peer refresh" + echo "" + echo "- Verified peers: ${verified}" + echo "- ID mismatches dropped: ${mismatch_count}" + echo "" + echo "Source: ${{ matrix.url }} (filtered to tcp_verified, then independently verified via P2P handshake)." + } > /tmp/pr_body.md + if [ "${mismatch_count}" -gt 0 ]; then + echo "⚠️ ID mismatches were detected and excluded — see job logs." >> /tmp/pr_body.md + jq -r '.[] | select(.status=="id_mismatch") | "- claimed=\(.claimed_id) remote=\(.remote_id) line=\(.line)"' /tmp/report.json >> /tmp/pr_body.md + fi + base="$(git show HEAD:${{ matrix.dir }}/peers.txt 2>/dev/null || true)" + if [ -n "$base" ]; then + added=$(comm -13 <(echo "$base" | sort) <(sort "${{ matrix.dir }}/peers.txt") | grep -c . || true) + removed=$(comm -23 <(echo "$base" | sort) <(sort "${{ matrix.dir }}/peers.txt") | grep -c . || true) + total=$(echo "$base" | grep -c . || echo 1) + churn=$(( (added + removed) * 100 / (total>0 ? total : 1) )) + echo "churn_pct=${churn}" >> "$GITHUB_OUTPUT" + if [ "${churn}" -gt "${CHURN_WARN_PCT}" ]; then + echo "labels=high-churn" >> "$GITHUB_OUTPUT" + else + echo "labels=" >> "$GITHUB_OUTPUT" + fi + fi + + - name: Open PR + uses: peter-evans/create-pull-request@v6 + with: + branch: peers/auto-update-${{ matrix.name }} + title: "chore(peers): refresh ${{ matrix.name }} peers.txt + addrbook.json" + body-path: /tmp/pr_body.md + labels: ${{ steps.meta.outputs.labels }} + add-paths: | + ${{ matrix.dir }}/peers.txt + ${{ matrix.dir }}/addrbook.json + assignees: rootulp + commit-message: "chore(peers): refresh ${{ matrix.name }} peers and addrbook" From 81b6316604881421d299f41b37191a5042b83273 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 12:56:37 -0700 Subject: [PATCH 11/13] ci(peers): harden churn math, guard jq install, show churn in PR body --- .github/workflows/update-peers.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-peers.yml b/.github/workflows/update-peers.yml index 8d6c66de..2a8156e6 100644 --- a/.github/workflows/update-peers.yml +++ b/.github/workflows/update-peers.yml @@ -34,8 +34,8 @@ jobs: with: go-version-file: scripts/peers/verifypeer/go.mod - - name: Install jq - run: sudo apt-get update && sudo apt-get install -y jq + - name: Ensure jq is available + run: command -v jq >/dev/null || { sudo apt-get update && sudo apt-get install -y jq; } - name: Fetch + filter candidates run: | @@ -80,9 +80,11 @@ jobs: if [ -n "$base" ]; then added=$(comm -13 <(echo "$base" | sort) <(sort "${{ matrix.dir }}/peers.txt") | grep -c . || true) removed=$(comm -23 <(echo "$base" | sort) <(sort "${{ matrix.dir }}/peers.txt") | grep -c . || true) - total=$(echo "$base" | grep -c . || echo 1) - churn=$(( (added + removed) * 100 / (total>0 ? total : 1) )) + total=$(echo "$base" | grep -c . || true) + (( total > 0 )) || total=1 + churn=$(( (added + removed) * 100 / total )) echo "churn_pct=${churn}" >> "$GITHUB_OUTPUT" + echo "- Churn vs current: ${churn}%" >> /tmp/pr_body.md if [ "${churn}" -gt "${CHURN_WARN_PCT}" ]; then echo "labels=high-churn" >> "$GITHUB_OUTPUT" else From 44deeb85deb92c5789409034c44e48229438f565 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 13:52:04 -0700 Subject: [PATCH 12/13] ci(peers): set min verified peers gate to 5 --- .github/workflows/update-peers.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-peers.yml b/.github/workflows/update-peers.yml index 2a8156e6..c763ec80 100644 --- a/.github/workflows/update-peers.yml +++ b/.github/workflows/update-peers.yml @@ -11,7 +11,7 @@ permissions: env: CELESTIA_APP_VERSION: v8.0.3 # bump to pull a newer addrbook generator - MIN_PEERS: "8" + MIN_PEERS: "5" CHURN_WARN_PCT: "60" jobs: From b8ae980e21250aeebf449f9997bec0029f29b590 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 1 Jun 2026 13:56:31 -0700 Subject: [PATCH 13/13] fix(peers): align -min default with CI gate (5) --- scripts/peers/verifypeer/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/peers/verifypeer/main.go b/scripts/peers/verifypeer/main.go index 079c3499..9cbbca77 100644 --- a/scripts/peers/verifypeer/main.go +++ b/scripts/peers/verifypeer/main.go @@ -72,7 +72,7 @@ func main() { in := flag.String("in", "", "input file of id@host:port candidate lines") out := flag.String("out", "", "output file for verified peer lines") report := flag.String("report", "", "output file for JSON verification report") - min := flag.Int("min", 8, "minimum verified peers required (else exit 1)") + min := flag.Int("min", 5, "minimum verified peers required (else exit 1)") concurrency := flag.Int("concurrency", 16, "max concurrent dials") timeoutSec := flag.Int("timeout", 5, "per-peer dial+handshake timeout in seconds") flag.Parse()