diff --git a/go.mod b/go.mod index 6b58adcfe..cb76ca894 100644 --- a/go.mod +++ b/go.mod @@ -13,13 +13,13 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-plugin v1.6.2 github.com/jackc/pgx/v4 v4.18.3 - github.com/jpillora/backoff v1.0.0 github.com/lib/pq v1.10.9 - github.com/pelletier/go-toml/v2 v2.2.0 - github.com/prometheus/client_golang v1.17.0 + github.com/pelletier/go-toml/v2 v2.2.2 + github.com/prometheus/client_golang v1.20.5 github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550 + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sync v0.10.0 @@ -29,6 +29,7 @@ require ( require ( contrib.go.opencensus.io/exporter/stackdriver v0.13.4 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/apache/arrow-go/v18 v18.0.0 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect @@ -46,10 +47,11 @@ require ( github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-playground/locales v0.13.0 // indirect - github.com/go-playground/universal-translator v0.17.0 // indirect - github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.1 // indirect github.com/goccy/go-json v0.10.3 // indirect + github.com/gogo/protobuf v1.3.3 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -70,19 +72,20 @@ require ( github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect + github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/leodido/go-urn v1.2.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/leodido/go-urn v1.2.1 // indirect github.com/linkedin/goavro/v2 v2.12.0 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/marcboeker/go-duckdb v1.8.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.35 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -90,14 +93,15 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.0.0 // indirect github.com/onsi/gomega v1.24.1 // indirect github.com/pierrec/lz4/v4 v4.1.21 // 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_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.60.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/riferrei/srclient v0.5.4 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect @@ -135,6 +139,7 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.30.0 // indirect go.opentelemetry.io/otel/trace v1.30.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect golang.org/x/crypto v0.28.0 // indirect diff --git a/go.sum b/go.sum index 3cf34d679..8b05d7c0b 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I= @@ -93,6 +94,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= +github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY= github.com/confluentinc/confluent-kafka-go/v2 v2.3.0 h1:icCHutJouWlQREayFwCc7lxDAhws08td+W3/gdqgZts= github.com/confluentinc/confluent-kafka-go/v2 v2.3.0/go.mod h1:/VTy8iEpe6mD9pkCH5BhijlUl8ulUXymKv1Qig5Rgb8= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= @@ -168,12 +171,12 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -370,6 +373,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 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.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 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= @@ -377,8 +381,10 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 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= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -418,8 +424,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= @@ -458,6 +462,8 @@ github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= 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= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -478,8 +484,10 @@ github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -493,21 +501,21 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= @@ -515,6 +523,8 @@ github.com/riferrei/srclient v0.5.4 h1:dfwyR5u23QF7beuVl2WemUY2KXh5+Sc4DHKyPXBNY github.com/riferrei/srclient v0.5.4/go.mod h1:vbkLmWcgYa7JgfPvuy/+K8fTS0p1bApqadxrxi/S1MI= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 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= @@ -528,6 +538,8 @@ github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIH github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ= github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= @@ -545,6 +557,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550 h1:rRs74zjDJ7do5aYEXSU/sOnLnlbYCNqM8BrvEx/0NH8= github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -581,8 +595,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= @@ -675,8 +690,9 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -710,6 +726,7 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= @@ -847,6 +864,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index c66251505..6a42422fe 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -7,31 +7,30 @@ replace github.com/smartcontractkit/chainlink-solana => ../ require ( github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/docker/docker v27.3.1+incompatible - github.com/gagliardetto/binary v0.7.7 - github.com/gagliardetto/solana-go v1.8.4 + github.com/gagliardetto/binary v0.8.0 + github.com/gagliardetto/solana-go v1.12.0 github.com/go-resty/resty/v2 v2.15.3 github.com/google/uuid v1.6.0 github.com/lib/pq v1.10.9 github.com/pelletier/go-toml/v2 v2.2.3 github.com/rs/zerolog v1.33.0 - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241210172617-6fd1891d0fbc + github.com/smartcontractkit/chainlink-common v0.4.1-0.20250113183410-42c3764c171e + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20250110142550-e2a9566d39f3 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212202512-52c2db4bff51 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212202512-52c2db4bff51 - github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241212202512-52c2db4bff51 - github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 - github.com/stretchr/testify v1.9.0 + github.com/smartcontractkit/chainlink/deployment v0.0.0-20250114144014-774d02662e80 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20250114144014-774d02662e80 + github.com/smartcontractkit/chainlink/v2 v2.19.0-ccip1.5.16-beta.0 + github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 + github.com/stretchr/testify v1.10.0 github.com/testcontainers/testcontainers-go v0.34.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 golang.org/x/sync v0.10.0 golang.org/x/text v0.21.0 gopkg.in/guregu/null.v4 v4.0.0 ) require ( - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -91,8 +90,8 @@ require ( github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -131,8 +130,7 @@ require ( github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -141,6 +139,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect + github.com/doyensec/safeurl v0.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect @@ -155,7 +154,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect github.com/gagliardetto/utilz v0.1.1 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect @@ -178,7 +177,7 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect @@ -273,7 +272,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -308,16 +307,16 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/cors v1.10.1 // indirect @@ -327,22 +326,24 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/segmentio/ksuid v1.0.4 // indirect + github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/slack-go/slack v0.15.0 // indirect - github.com/smartcontractkit/chain-selectors v1.0.34 // indirect + github.com/smartcontractkit/chain-selectors v1.0.36 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241211150100-7683331f64a0 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20250110181647-9dba278f2103 // indirect github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect @@ -355,13 +356,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/test-go/testify v1.1.4 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect @@ -389,7 +389,6 @@ require ( go.dedis.ch/kyber/v3 v3.1.0 // indirect go.etcd.io/bbolt v1.3.9 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect @@ -416,14 +415,14 @@ require ( go.uber.org/ratelimit v0.3.1 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/crypto v0.28.0 // indirect - golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.25.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.26.0 // indirect + golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 7f20fb5c2..f21aba91d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -75,7 +70,6 @@ cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8 dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -103,8 +97,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -135,7 +127,6 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -147,7 +138,6 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1L github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= @@ -171,8 +161,6 @@ github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinR github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= @@ -227,7 +215,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -250,10 +237,11 @@ github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40 github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= @@ -330,9 +318,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -340,7 +326,6 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -381,7 +366,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -395,23 +379,18 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/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/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= 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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= @@ -424,6 +403,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= +github.com/doyensec/safeurl v0.2.1 h1:DY15JorEfQsnpBWhBkVQIkaif2jfxCC14PIuGDsjDVs= +github.com/doyensec/safeurl v0.2.1/go.mod h1:wzSXqC/6Z410qHz23jtBWT+wQ8yTxcY0p8bZH/4EZIg= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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= @@ -459,7 +440,6 @@ github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSY github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= @@ -476,15 +456,15 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= github.com/gagliardetto/hashsearch v0.0.0-20191005111333-09dd671e19f9/go.mod h1:513DXpQPzeRo7d4dsCP3xO3XI8hgvruMl9njxyQeraQ= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gagliardetto/utilz v0.1.1 h1:/etW4hl607emKg6R6Lj9jRJ9d6ue2AQOyjhuAwjzs1U= @@ -496,8 +476,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= -github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= +github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= +github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -553,8 +533,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= -github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= @@ -593,7 +573,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -629,7 +608,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -730,15 +708,12 @@ github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMN github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -797,7 +772,6 @@ github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -885,10 +859,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -897,7 +869,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -919,7 +890,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -966,7 +936,6 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -980,7 +949,6 @@ github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSl github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -989,8 +957,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -998,8 +964,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -1059,7 +1025,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -1080,7 +1045,6 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -1088,7 +1052,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1133,9 +1096,8 @@ github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNH github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -1158,7 +1120,6 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= @@ -1169,21 +1130,17 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1193,11 +1150,10 @@ github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC github.com/riferrei/srclient v0.5.4 h1:dfwyR5u23QF7beuVl2WemUY2KXh5+Sc4DHKyPXBNYuc= github.com/riferrei/srclient v0.5.4/go.mod h1:vbkLmWcgYa7JgfPvuy/+K8fTS0p1bApqadxrxi/S1MI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1226,8 +1182,8 @@ github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQ github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= @@ -1263,42 +1219,48 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= +github.com/smartcontractkit/chain-selectors v1.0.36 h1:KSpO8I+JOiuyN4FuXsV471sPorGF//PAqwq2Cm4gRK0= +github.com/smartcontractkit/chain-selectors v1.0.36/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241211150100-7683331f64a0 h1:/1L+v4SxUD2K5RMRbfByyLfePMAgQKeD0onSetPnGmA= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241211150100-7683331f64a0/go.mod h1:F8xQAIW0ymb2BZhqn89sWZLXreJhM5KDVF6Qb4y44N0= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550 h1:rRs74zjDJ7do5aYEXSU/sOnLnlbYCNqM8BrvEx/0NH8= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241223143929-db7919d60550/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250110181647-9dba278f2103 h1:TeWnxdgSO2cYCKcBMwdkRcs/YdhSvXoWqqw7QWz/KeI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20250110181647-9dba278f2103/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b h1:UBXi9Yj8YSMHDDaxQLu273x1fWjyEL9xP58nuJsqZfg= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250103152858-8973fd0c912b/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= +github.com/smartcontractkit/chainlink-common v0.4.1-0.20250113183410-42c3764c171e h1:l1npEX9O1Y1R4ss6yNPlggxFOdhPWmvD3tIMZkOzuDU= +github.com/smartcontractkit/chainlink-common v0.4.1-0.20250113183410-42c3764c171e/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db h1:N1RH1hSr2ACzOFc9hkCcjE8pRBTdcU3p8nsTJByaLes= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241202141438-a90db35252db/go.mod h1:yjb9d4q7+m8aGbjfTbkNoNuA4PeSxcUszsSZHDrvS0E= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260 h1:See2isL6KdrTJDlVKWv8qiyYqWhYUcubU2e5yKXV1oY= +github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250115203616-a2ea5e50b260/go.mod h1:4JqpgFy01LaqG1yM2iFTzwX3ZgcAvW9WdstBZQgPHzU= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtOAzKS4PrPIiJX65BGo1aYiYZxFVEW+jc= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2 h1:nTUoe7GZLw17nPLV5t3Vgf4U4pf+VW0Uko5xpNiKdKU= +github.com/smartcontractkit/chainlink-testing-framework/framework v0.4.2-0.20250110073248-456673e8eea2/go.mod h1:mMUqvS3BZfvN1OfK4OFTYf1+T0X6nwmSXJM2keaPsSM= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 h1:9PMwKNqFKc5FXf4VchyD3CGzZelnSgi13fgVdT2X7T4= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19/go.mod h1:ag7LEgejsVtPXaUNkcoFPpAoDkl1J8V2HSbqVUxfEtk= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212202512-52c2db4bff51 h1:BfKIOb8ZCa0JgMCEt4nkfirJyliK5EaMj6wHWhnX6VI= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241212202512-52c2db4bff51/go.mod h1:aS1p53uW9YsAAWT8cg7RHVvl3DHp8GtMZTI2DWqAbOQ= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212202512-52c2db4bff51 h1:x3UfhE6zCEqJfU7OED68lYYKmTq0oA3u0Lu7W7VU44Q= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241212202512-52c2db4bff51/go.mod h1:e6VA6bgpQHuXHVwZ9vHJdKJou6aJlrMZ1HmTuVenbwo= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241212202512-52c2db4bff51 h1:WqIpU1iki+jN2a36t7Mkk+clU6VdSOe3XSEpX8LoDjw= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241212202512-52c2db4bff51/go.mod h1:rwf5KD0es3Q4n0iqtld8ZCDUg6bAoYcqs186F9FcQBQ= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20250114144014-774d02662e80 h1:TD5BL6wShuFOs06IRbChkA/kcFDm4eC0Q4Xk0Vl7U5k= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20250114144014-774d02662e80/go.mod h1:hwjGHpH2odH6uswne9Fuq5FFwqbq7hiEz81UKq+60aY= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20250114144014-774d02662e80 h1:m0fCOMZsT3XNIuHGDZFV0Hh/gUCjQ8gLGMGzup4wFEA= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20250114144014-774d02662e80/go.mod h1:W0J1UKnhkQwEpaxDs21sTMNZSEzXasjxKMhRMx88hNM= +github.com/smartcontractkit/chainlink/v2 v2.19.0-ccip1.5.16-beta.0 h1:HNYNbjcsJo+89wlleUAHSRHfD7FhWViJZDSiExFNdIc= +github.com/smartcontractkit/chainlink/v2 v2.19.0-ccip1.5.16-beta.0/go.mod h1:nsmzoKkzkc/8RVB+9My4EDPBf3sjbPtBo+elgd9mEBA= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= -github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919 h1:IpGoPTXpvllN38kT2z2j13sifJMz4nbHglidvop7mfg= +github.com/smartcontractkit/libocr v0.0.0-20241223215956-e5b78d8e3919/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de h1:n0w0rKF+SVM+S3WNlup6uabXj2zFlFNfrlsKCMMb/co= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= @@ -1309,7 +1271,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1324,7 +1285,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1334,15 +1294,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1362,8 +1320,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F 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.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1373,9 +1332,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= @@ -1384,12 +1340,10 @@ github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrj github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.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.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1397,7 +1351,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1420,20 +1373,14 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1441,7 +1388,6 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1466,18 +1412,15 @@ go.dedis.ch/kyber/v3 v3.1.0/go.mod h1:kXy7p3STAurkADD+/aZcsznZGKVHEqbtmdIzvPfrs1 go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1547,20 +1490,16 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 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/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1583,10 +1522,9 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1597,8 +1535,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1627,15 +1565,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1681,8 +1618,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1717,7 +1654,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1733,7 +1669,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1796,19 +1731,18 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -1846,7 +1780,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1892,8 +1825,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1911,7 +1844,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1936,7 +1868,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1946,7 +1877,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1995,9 +1925,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -2048,16 +1976,13 @@ gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 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.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2108,7 +2033,6 @@ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYm pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/integration-tests/relayinterface/chain_components_test.go b/integration-tests/relayinterface/chain_components_test.go index c32507e49..d3b85557a 100644 --- a/integration-tests/relayinterface/chain_components_test.go +++ b/integration-tests/relayinterface/chain_components_test.go @@ -384,7 +384,7 @@ func (h *helper) waitForTX(t *testing.T, sig solana.Signature, commitment rpc.Co defer sub.Unsubscribe() - res, err := sub.Recv() + res, err := sub.Recv(tests.Context(t)) require.NoError(t, err) if res.Value.Err != nil { diff --git a/integration-tests/smoke/event_loader_test.go b/integration-tests/smoke/event_loader_test.go index cd4bc678c..b3d001441 100644 --- a/integration-tests/smoke/event_loader_test.go +++ b/integration-tests/smoke/event_loader_test.go @@ -282,7 +282,7 @@ func (s *logSender) queueTX(sig solana.Signature, commitment rpc.CommitmentType) defer sub.Unsubscribe() - res, err := sub.Recv() + res, err := sub.Recv(context.Background()) if err != nil { return err } diff --git a/integration-tests/solclient/solclient.go b/integration-tests/solclient/solclient.go index 2d5f52ac7..74cad3399 100644 --- a/integration-tests/solclient/solclient.go +++ b/integration-tests/solclient/solclient.go @@ -178,7 +178,7 @@ func (c *Client) TXSync(name string, commitment rpc.CommitmentType, instr []sola return err } defer sub.Unsubscribe() - res, err := sub.Recv() + res, err := sub.Recv(context.Background()) if err != nil { return err } @@ -196,7 +196,7 @@ func (c *Client) queueTX(sig solana.Signature, commitment rpc.CommitmentType) { return err } defer sub.Unsubscribe() - res, err := sub.Recv() + res, err := sub.Recv(context.Background()) if err != nil { return err } diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 1f482b7f5..36a86c4db 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -265,13 +265,9 @@ func (c *TestConfig) GetNodeConfigTOML() (string, error) { url = c.GetURL() } - mnConfig := solcfg.MultiNodeConfig{ - MultiNode: solcfg.MultiNode{ - Enabled: ptr.Ptr(true), - SyncThreshold: ptr.Ptr(uint32(170)), - }, - } - mnConfig.SetDefaults() + mnConfig := solcfg.NewDefaultMultiNodeConfig() + mnConfig.MultiNode.Enabled = ptr.Ptr(true) + mnConfig.MultiNode.SyncThreshold = ptr.Ptr(uint32(170)) var nodes []*solcfg.Node for i, u := range url { diff --git a/pkg/solana/chain.go b/pkg/solana/chain.go index d137e75de..017a60283 100644 --- a/pkg/solana/chain.go +++ b/pkg/solana/chain.go @@ -23,9 +23,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/utils" + mn "github.com/smartcontractkit/chainlink-framework/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana/internal" "github.com/smartcontractkit/chainlink-solana/pkg/solana/monitor" @@ -266,7 +266,7 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L sendOnlyNodes = append(sendOnlyNodes, newSendOnly) } else { newNode := mn.NewNode[mn.StringID, *client.Head, *client.MultiNodeClient]( - mnCfg, mnCfg, lggr, *nodeInfo.URL.URL(), nil, *nodeInfo.Name, + mnCfg, mnCfg, lggr, nodeInfo.URL.URL(), nil, *nodeInfo.Name, i, mn.StringID(id), 0, rpcClient, chainFamily) nodes = append(nodes, newNode) } diff --git a/pkg/solana/chain_test.go b/pkg/solana/chain_test.go index c2182e7c1..df51c313f 100644 --- a/pkg/solana/chain_test.go +++ b/pkg/solana/chain_test.go @@ -26,9 +26,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + mn "github.com/smartcontractkit/chainlink-framework/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana/fees" "github.com/smartcontractkit/chainlink-solana/pkg/solana/txm/mocks" @@ -335,12 +335,8 @@ func TestSolanaChain_MultiNode_GetClient(t *testing.T) { ch := solcfg.Chain{} ch.SetDefaults() - mnCfg := solcfg.MultiNodeConfig{ - MultiNode: solcfg.MultiNode{ - Enabled: ptr(true), - }, - } - mnCfg.SetDefaults() + mnCfg := solcfg.NewDefaultMultiNodeConfig() + mnCfg.MultiNode.Enabled = ptr(true) cfg := &solcfg.TOMLConfig{ ChainID: ptr("devnet"), diff --git a/pkg/solana/client/classify_errors.go b/pkg/solana/client/classify_errors.go index ae3402694..deea39a5b 100644 --- a/pkg/solana/client/classify_errors.go +++ b/pkg/solana/client/classify_errors.go @@ -5,7 +5,7 @@ import ( "github.com/gagliardetto/solana-go" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" + mn "github.com/smartcontractkit/chainlink-framework/multinode" ) // Solana error patters diff --git a/pkg/solana/client/classify_errors_test.go b/pkg/solana/client/classify_errors_test.go index 29d6a3bc0..2efab4a4a 100644 --- a/pkg/solana/client/classify_errors_test.go +++ b/pkg/solana/client/classify_errors_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" + mn "github.com/smartcontractkit/chainlink-framework/multinode" ) func TestClassifySendError(t *testing.T) { diff --git a/pkg/solana/client/client.go b/pkg/solana/client/client.go index 5eaa37b89..13e0cab2d 100644 --- a/pkg/solana/client/client.go +++ b/pkg/solana/client/client.go @@ -11,8 +11,8 @@ import ( "golang.org/x/sync/singleflight" "github.com/smartcontractkit/chainlink-common/pkg/logger" + mn "github.com/smartcontractkit/chainlink-framework/multinode" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana/monitor" ) diff --git a/pkg/solana/client/client_test.go b/pkg/solana/client/client_test.go index 6ca3c1727..d88b6f5d5 100644 --- a/pkg/solana/client/client_test.go +++ b/pkg/solana/client/client_test.go @@ -20,8 +20,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + mn "github.com/smartcontractkit/chainlink-framework/multinode" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana/monitor" ) diff --git a/pkg/solana/client/mocks/reader_writer.go b/pkg/solana/client/mocks/reader_writer.go index 7c72ca183..875d85620 100644 --- a/pkg/solana/client/mocks/reader_writer.go +++ b/pkg/solana/client/mocks/reader_writer.go @@ -5,10 +5,11 @@ package mocks import ( context "context" - rpc "github.com/gagliardetto/solana-go/rpc" - multinode "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" + multinode "github.com/smartcontractkit/chainlink-framework/multinode" mock "github.com/stretchr/testify/mock" + rpc "github.com/gagliardetto/solana-go/rpc" + solana "github.com/gagliardetto/solana-go" ) diff --git a/pkg/solana/client/multi_client.go b/pkg/solana/client/multi_client.go index eb159e114..ff397910f 100644 --- a/pkg/solana/client/multi_client.go +++ b/pkg/solana/client/multi_client.go @@ -6,7 +6,7 @@ import ( "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/rpc" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" + mn "github.com/smartcontractkit/chainlink-framework/multinode" ) var _ ReaderWriter = (*MultiClient)(nil) diff --git a/pkg/solana/client/multinode/ctx.go b/pkg/solana/client/multinode/ctx.go deleted file mode 100644 index 57b2fc8a8..000000000 --- a/pkg/solana/client/multinode/ctx.go +++ /dev/null @@ -1,17 +0,0 @@ -package client - -import "context" - -type multiNodeContextKey int - -const ( - contextKeyHeathCheckRequest multiNodeContextKey = iota + 1 -) - -func CtxAddHealthCheckFlag(ctx context.Context) context.Context { - return context.WithValue(ctx, contextKeyHeathCheckRequest, struct{}{}) -} - -func CtxIsHeathCheckRequest(ctx context.Context) bool { - return ctx.Value(contextKeyHeathCheckRequest) != nil -} diff --git a/pkg/solana/client/multinode/models.go b/pkg/solana/client/multinode/models.go deleted file mode 100644 index 526bb25c8..000000000 --- a/pkg/solana/client/multinode/models.go +++ /dev/null @@ -1,121 +0,0 @@ -package client - -import ( - "bytes" - "fmt" -) - -type SendTxReturnCode int - -// SendTxReturnCode is a generalized client error that dictates what should be the next action, depending on the RPC error response. -const ( - Successful SendTxReturnCode = iota + 1 - Fatal // Unrecoverable error. Most likely the attempt should be thrown away. - Retryable // The error returned by the RPC indicates that if we retry with the same attempt, the tx will eventually go through. - Underpriced // Attempt was underpriced. New estimation is needed with bumped gas price. - Unknown // Tx failed with an error response that is not recognized by the client. - Unsupported // Attempt failed with an error response that is not supported by the client for the given chain. - TransactionAlreadyKnown // The transaction that was sent has already been received by the RPC. - InsufficientFunds // Tx was rejected due to insufficient funds. - ExceedsMaxFee // Attempt's fee was higher than the node's limit and got rejected. - FeeOutOfValidRange // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price. - TerminallyStuck // The error returned when a transaction is or could get terminally stuck in the mempool without any chance of inclusion. - sendTxReturnCodeLen // tracks the number of errors. Must always be last -) - -// sendTxSevereErrors - error codes which signal that transaction would never be accepted in its current form by the node -var sendTxSevereErrors = []SendTxReturnCode{Fatal, Underpriced, Unsupported, ExceedsMaxFee, FeeOutOfValidRange, Unknown} - -// sendTxSuccessfulCodes - error codes which signal that transaction was accepted by the node -var sendTxSuccessfulCodes = []SendTxReturnCode{Successful, TransactionAlreadyKnown} - -func (c SendTxReturnCode) String() string { - switch c { - case Successful: - return "Successful" - case Fatal: - return "Fatal" - case Retryable: - return "Retryable" - case Underpriced: - return "Underpriced" - case Unknown: - return "Unknown" - case Unsupported: - return "Unsupported" - case TransactionAlreadyKnown: - return "TransactionAlreadyKnown" - case InsufficientFunds: - return "InsufficientFunds" - case ExceedsMaxFee: - return "ExceedsMaxFee" - case FeeOutOfValidRange: - return "FeeOutOfValidRange" - case TerminallyStuck: - return "TerminallyStuck" - default: - return fmt.Sprintf("SendTxReturnCode(%d)", c) - } -} - -type NodeTier int - -const ( - Primary = NodeTier(iota) - Secondary -) - -func (n NodeTier) String() string { - switch n { - case Primary: - return "primary" - case Secondary: - return "secondary" - default: - return fmt.Sprintf("NodeTier(%d)", n) - } -} - -// syncStatus - defines problems related to RPC's state synchronization. Can be used as a bitmask to define multiple issues -type syncStatus int - -const ( - // syncStatusSynced - RPC is fully synced - syncStatusSynced = 0 - // syncStatusNotInSyncWithPool - RPC is lagging behind the highest block observed within the pool of RPCs - syncStatusNotInSyncWithPool syncStatus = 1 << iota - // syncStatusNoNewHead - RPC failed to produce a new head for too long - syncStatusNoNewHead - // syncStatusNoNewFinalizedHead - RPC failed to produce a new finalized head for too long - syncStatusNoNewFinalizedHead - syncStatusLen -) - -func (s syncStatus) String() string { - if s == syncStatusSynced { - return "Synced" - } - var result bytes.Buffer - for i := syncStatusNotInSyncWithPool; i < syncStatusLen; i = i << 1 { - if i&s == 0 { - continue - } - result.WriteString(i.string()) - result.WriteString(",") - } - result.Truncate(result.Len() - 1) - return result.String() -} - -func (s syncStatus) string() string { - switch s { - case syncStatusNotInSyncWithPool: - return "NotInSyncWithRPCPool" - case syncStatusNoNewHead: - return "NoNewHead" - case syncStatusNoNewFinalizedHead: - return "NoNewFinalizedHead" - default: - return fmt.Sprintf("syncStatus(%d)", s) - } -} diff --git a/pkg/solana/client/multinode/multi_node.go b/pkg/solana/client/multinode/multi_node.go deleted file mode 100644 index fa05a75cd..000000000 --- a/pkg/solana/client/multinode/multi_node.go +++ /dev/null @@ -1,377 +0,0 @@ -package client - -import ( - "context" - "errors" - "fmt" - "math/big" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -var ( - // PromMultiNodeRPCNodeStates reports current RPC node state - PromMultiNodeRPCNodeStates = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "solana_multi_node_states", - Help: "The number of RPC nodes currently in the given state for the given chain", - }, []string{"network", "chainId", "state"}) - ErroringNodeError = fmt.Errorf("no live nodes available") -) - -// MultiNode is a generalized multi node client interface that includes methods to interact with different chains. -// It also handles multiple node RPC connections simultaneously. -type MultiNode[ - CHAIN_ID ID, - RPC any, -] struct { - services.StateMachine - primaryNodes []Node[CHAIN_ID, RPC] - sendOnlyNodes []SendOnlyNode[CHAIN_ID, RPC] - chainID CHAIN_ID - lggr logger.SugaredLogger - selectionMode string - nodeSelector NodeSelector[CHAIN_ID, RPC] - leaseDuration time.Duration - leaseTicker *time.Ticker - chainFamily string - reportInterval time.Duration - deathDeclarationDelay time.Duration - - activeMu sync.RWMutex - activeNode Node[CHAIN_ID, RPC] - - chStop services.StopChan - wg sync.WaitGroup -} - -func NewMultiNode[ - CHAIN_ID ID, - RPC any, -]( - lggr logger.Logger, - selectionMode string, // type of the "best" RPC selector (e.g HighestHead, RoundRobin, etc.) - leaseDuration time.Duration, // defines interval on which new "best" RPC should be selected - primaryNodes []Node[CHAIN_ID, RPC], - sendOnlyNodes []SendOnlyNode[CHAIN_ID, RPC], - chainID CHAIN_ID, // configured chain ID (used to verify that passed primaryNodes belong to the same chain) - chainFamily string, // name of the chain family - used in the metrics - deathDeclarationDelay time.Duration, -) *MultiNode[CHAIN_ID, RPC] { - nodeSelector := newNodeSelector(selectionMode, primaryNodes) - // Prometheus' default interval is 15s, set this to under 7.5s to avoid - // aliasing (see: https://en.wikipedia.org/wiki/Nyquist_frequency) - const reportInterval = 6500 * time.Millisecond - c := &MultiNode[CHAIN_ID, RPC]{ - primaryNodes: primaryNodes, - sendOnlyNodes: sendOnlyNodes, - chainID: chainID, - lggr: logger.Sugared(lggr).Named("MultiNode").With("chainID", chainID.String()), - selectionMode: selectionMode, - nodeSelector: nodeSelector, - chStop: make(services.StopChan), - leaseDuration: leaseDuration, - chainFamily: chainFamily, - reportInterval: reportInterval, - deathDeclarationDelay: deathDeclarationDelay, - } - - c.lggr.Debugf("The MultiNode is configured to use NodeSelectionMode: %s", selectionMode) - - return c -} - -func (c *MultiNode[CHAIN_ID, RPC]) ChainID() CHAIN_ID { - return c.chainID -} - -func (c *MultiNode[CHAIN_ID, RPC]) DoAll(ctx context.Context, do func(ctx context.Context, rpc RPC, isSendOnly bool)) error { - var err error - ok := c.IfNotStopped(func() { - callsCompleted := 0 - for _, n := range c.primaryNodes { - select { - case <-ctx.Done(): - err = ctx.Err() - return - default: - if n.State() != NodeStateAlive { - continue - } - do(ctx, n.RPC(), false) - callsCompleted++ - } - } - if callsCompleted == 0 { - err = ErroringNodeError - } - - for _, n := range c.sendOnlyNodes { - select { - case <-ctx.Done(): - err = ctx.Err() - return - default: - if n.State() != NodeStateAlive { - continue - } - do(ctx, n.RPC(), true) - } - } - }) - if !ok { - return errors.New("MultiNode is stopped") - } - return err -} - -func (c *MultiNode[CHAIN_ID, RPC]) NodeStates() map[string]string { - states := map[string]string{} - for _, n := range c.primaryNodes { - states[n.Name()] = n.State().String() - } - for _, n := range c.sendOnlyNodes { - states[n.Name()] = n.State().String() - } - return states -} - -// Start starts every node in the pool -// -// Nodes handle their own redialing and runloops, so this function does not -// return any error if the nodes aren't available -func (c *MultiNode[CHAIN_ID, RPC]) Start(ctx context.Context) error { - return c.StartOnce("MultiNode", func() (merr error) { - if len(c.primaryNodes) == 0 { - return fmt.Errorf("no available nodes for chain %s", c.chainID.String()) - } - var ms services.MultiStart - for _, n := range c.primaryNodes { - if n.ConfiguredChainID().String() != c.chainID.String() { - return ms.CloseBecause(fmt.Errorf("node %s has configured chain ID %s which does not match multinode configured chain ID of %s", n.String(), n.ConfiguredChainID().String(), c.chainID.String())) - } - n.SetPoolChainInfoProvider(c) - // node will handle its own redialing and automatic recovery - if err := ms.Start(ctx, n); err != nil { - return err - } - } - for _, s := range c.sendOnlyNodes { - if s.ConfiguredChainID().String() != c.chainID.String() { - return ms.CloseBecause(fmt.Errorf("sendonly node %s has configured chain ID %s which does not match multinode configured chain ID of %s", s.String(), s.ConfiguredChainID().String(), c.chainID.String())) - } - if err := ms.Start(ctx, s); err != nil { - return err - } - } - c.wg.Add(1) - go c.runLoop() - - if c.leaseDuration.Seconds() > 0 && c.selectionMode != NodeSelectionModeRoundRobin { - c.lggr.Infof("The MultiNode will switch to best node every %s", c.leaseDuration.String()) - c.wg.Add(1) - go c.checkLeaseLoop() - } else { - c.lggr.Info("Best node switching is disabled") - } - - return nil - }) -} - -// Close tears down the MultiNode and closes all nodes -func (c *MultiNode[CHAIN_ID, RPC]) Close() error { - return c.StopOnce("MultiNode", func() error { - close(c.chStop) - c.wg.Wait() - - return services.CloseAll(services.MultiCloser(c.primaryNodes), services.MultiCloser(c.sendOnlyNodes)) - }) -} - -// SelectRPC returns an RPC of an active node. If there are no active nodes it returns an error. -// Call this method from your chain-specific client implementation to access any chain-specific rpc calls. -func (c *MultiNode[CHAIN_ID, RPC]) SelectRPC() (rpc RPC, err error) { - n, err := c.selectNode() - if err != nil { - return rpc, err - } - return n.RPC(), nil -} - -// selectNode returns the active Node, if it is still NodeStateAlive, otherwise it selects a new one from the NodeSelector. -func (c *MultiNode[CHAIN_ID, RPC]) selectNode() (node Node[CHAIN_ID, RPC], err error) { - c.activeMu.RLock() - node = c.activeNode - c.activeMu.RUnlock() - if node != nil && node.State() == NodeStateAlive { - return // still alive - } - - // select a new one - c.activeMu.Lock() - defer c.activeMu.Unlock() - node = c.activeNode - if node != nil && node.State() == NodeStateAlive { - return // another goroutine beat us here - } - - if c.activeNode != nil { - c.activeNode.UnsubscribeAllExceptAliveLoop() - } - c.activeNode = c.nodeSelector.Select() - - if c.activeNode == nil { - c.lggr.Criticalw("No live RPC nodes available", "NodeSelectionMode", c.nodeSelector.Name()) - errmsg := fmt.Errorf("no live nodes available for chain %s", c.chainID.String()) - c.SvcErrBuffer.Append(errmsg) - err = ErroringNodeError - } - - return c.activeNode, err -} - -// LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being marked as out-of-sync. -// Return highest ChainInfo most recently received by the alive nodes. -// E.g. If Node A's the most recent block is 10 and highest 15 and for Node B it's - 12 and 14. This method will return 12. -func (c *MultiNode[CHAIN_ID, RPC]) LatestChainInfo() (int, ChainInfo) { - var nLiveNodes int - ch := ChainInfo{ - TotalDifficulty: big.NewInt(0), - } - for _, n := range c.primaryNodes { - if s, nodeChainInfo := n.StateAndLatest(); s == NodeStateAlive { - nLiveNodes++ - ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) - ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) - ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) - } - } - return nLiveNodes, ch -} - -// HighestUserObservations - returns highest ChainInfo ever observed by any user of the MultiNode -func (c *MultiNode[CHAIN_ID, RPC]) HighestUserObservations() ChainInfo { - ch := ChainInfo{ - TotalDifficulty: big.NewInt(0), - } - for _, n := range c.primaryNodes { - nodeChainInfo := n.HighestUserObservations() - ch.BlockNumber = max(ch.BlockNumber, nodeChainInfo.BlockNumber) - ch.FinalizedBlockNumber = max(ch.FinalizedBlockNumber, nodeChainInfo.FinalizedBlockNumber) - ch.TotalDifficulty = MaxTotalDifficulty(ch.TotalDifficulty, nodeChainInfo.TotalDifficulty) - } - return ch -} - -func (c *MultiNode[CHAIN_ID, RPC]) checkLease() { - bestNode := c.nodeSelector.Select() - for _, n := range c.primaryNodes { - // Terminate client subscriptions. Services are responsible for reconnecting, which will be routed to the new - // best node. Only terminate connections with more than 1 subscription to account for the aliveLoop subscription - if n.State() == NodeStateAlive && n != bestNode { - c.lggr.Infof("Switching to best node from %q to %q", n.String(), bestNode.String()) - n.UnsubscribeAllExceptAliveLoop() - } - } - - c.activeMu.Lock() - defer c.activeMu.Unlock() - if bestNode != c.activeNode { - if c.activeNode != nil { - c.activeNode.UnsubscribeAllExceptAliveLoop() - } - c.activeNode = bestNode - } -} - -func (c *MultiNode[CHAIN_ID, RPC]) checkLeaseLoop() { - defer c.wg.Done() - c.leaseTicker = time.NewTicker(c.leaseDuration) - defer c.leaseTicker.Stop() - - for { - select { - case <-c.leaseTicker.C: - c.checkLease() - case <-c.chStop: - return - } - } -} - -func (c *MultiNode[CHAIN_ID, RPC]) runLoop() { - defer c.wg.Done() - - nodeStates := make([]nodeWithState, len(c.primaryNodes)) - for i, n := range c.primaryNodes { - nodeStates[i] = nodeWithState{ - Node: n.String(), - State: n.State().String(), - DeadSince: nil, - } - } - - c.report(nodeStates) - - monitor := services.NewTicker(c.reportInterval) - defer monitor.Stop() - - for { - select { - case <-monitor.C: - c.report(nodeStates) - case <-c.chStop: - return - } - } -} - -type nodeWithState struct { - Node string - State string - DeadSince *time.Time -} - -func (c *MultiNode[CHAIN_ID, RPC]) report(nodesStateInfo []nodeWithState) { - start := time.Now() - var dead int - counts := make(map[NodeState]int) - for i, n := range c.primaryNodes { - state := n.State() - counts[state]++ - nodesStateInfo[i].State = state.String() - if state == NodeStateAlive { - nodesStateInfo[i].DeadSince = nil - continue - } - - if nodesStateInfo[i].DeadSince == nil { - nodesStateInfo[i].DeadSince = &start - } - - if start.Sub(*nodesStateInfo[i].DeadSince) >= c.deathDeclarationDelay { - dead++ - } - } - for _, state := range allNodeStates { - count := counts[state] - PromMultiNodeRPCNodeStates.WithLabelValues(c.chainFamily, c.chainID.String(), state.String()).Set(float64(count)) - } - - total := len(c.primaryNodes) - live := total - dead - c.lggr.Tracew(fmt.Sprintf("MultiNode state: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) - if total == dead { - rerr := fmt.Errorf("no primary nodes available: 0/%d nodes are alive", total) - c.lggr.Criticalw(rerr.Error(), "nodeStates", nodesStateInfo) - c.SvcErrBuffer.Append(rerr) - } else if dead > 0 { - c.lggr.Warnw(fmt.Sprintf("At least one primary node is dead: %d/%d nodes are alive", live, total), "nodeStates", nodesStateInfo) - } -} diff --git a/pkg/solana/client/multinode/node.go b/pkg/solana/client/multinode/node.go deleted file mode 100644 index afdece741..000000000 --- a/pkg/solana/client/multinode/node.go +++ /dev/null @@ -1,328 +0,0 @@ -package client - -import ( - "context" - "errors" - "fmt" - "net/url" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -const QueryTimeout = 10 * time.Second - -var errInvalidChainID = errors.New("invalid chain id") - -var ( - promPoolRPCNodeVerifies = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_verifies", - Help: "The total number of chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) - promPoolRPCNodeVerifiesFailed = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_verifies_failed", - Help: "The total number of failed chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) - promPoolRPCNodeVerifiesSuccess = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_verifies_success", - Help: "The total number of successful chain ID verifications for the given RPC node", - }, []string{"network", "chainID", "nodeName"}) -) - -type NodeConfig interface { - PollFailureThreshold() uint32 - PollInterval() time.Duration - SelectionMode() string - SyncThreshold() uint32 - NodeIsSyncingEnabled() bool - FinalizedBlockPollInterval() time.Duration - EnforceRepeatableRead() bool - DeathDeclarationDelay() time.Duration -} - -type ChainConfig interface { - NodeNoNewHeadsThreshold() time.Duration - NoNewFinalizedHeadsThreshold() time.Duration - FinalityDepth() uint32 - FinalityTagEnabled() bool - FinalizedBlockOffset() uint32 -} - -type Node[ - CHAIN_ID ID, - RPC any, -] interface { - // State returns most accurate state of the Node on the moment of call. - // While some of the checks may be performed in the background and State may return cached value, critical, like - // `FinalizedBlockOutOfSync`, must be executed upon every call. - State() NodeState - // StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. - StateAndLatest() (NodeState, ChainInfo) - // HighestUserObservations - returns highest ChainInfo ever observed by underlying RPC excluding results of health check requests - HighestUserObservations() ChainInfo - SetPoolChainInfoProvider(PoolChainInfoProvider) - // Name is a unique identifier for this node. - Name() string - // String - returns string representation of the node, useful for debugging (name + URLS used to connect to the RPC) - String() string - RPC() RPC - // UnsubscribeAllExceptAliveLoop - closes all subscriptions except the aliveLoop subscription - UnsubscribeAllExceptAliveLoop() - ConfiguredChainID() CHAIN_ID - // Order - returns priority order configured for the RPC - Order() int32 - // Start - starts health checks - Start(context.Context) error - Close() error -} - -type node[ - CHAIN_ID ID, - HEAD Head, - RPC RPCClient[CHAIN_ID, HEAD], -] struct { - services.StateMachine - lfcLog logger.Logger - name string - id int - chainID CHAIN_ID - nodePoolCfg NodeConfig - chainCfg ChainConfig - order int32 - chainFamily string - - ws url.URL - http *url.URL - - rpc RPC - - stateMu sync.RWMutex // protects state* fields - state NodeState - - poolInfoProvider PoolChainInfoProvider - - stopCh services.StopChan - // wg waits for subsidiary goroutines - wg sync.WaitGroup - - healthCheckSubs []Subscription -} - -func NewNode[ - CHAIN_ID ID, - HEAD Head, - RPC RPCClient[CHAIN_ID, HEAD], -]( - nodeCfg NodeConfig, - chainCfg ChainConfig, - lggr logger.Logger, - wsuri url.URL, - httpuri *url.URL, - name string, - id int, - chainID CHAIN_ID, - nodeOrder int32, - rpc RPC, - chainFamily string, -) Node[CHAIN_ID, RPC] { - n := new(node[CHAIN_ID, HEAD, RPC]) - n.name = name - n.id = id - n.chainID = chainID - n.nodePoolCfg = nodeCfg - n.chainCfg = chainCfg - n.ws = wsuri - n.order = nodeOrder - if httpuri != nil { - n.http = httpuri - } - n.stopCh = make(services.StopChan) - lggr = logger.Named(lggr, "Node") - lggr = logger.With(lggr, - "nodeTier", Primary.String(), - "nodeName", name, - "node", n.String(), - "chainID", chainID, - "nodeOrder", n.order, - ) - n.lfcLog = logger.Named(lggr, "Lifecycle") - n.rpc = rpc - n.chainFamily = chainFamily - return n -} - -func (n *node[CHAIN_ID, HEAD, RPC]) String() string { - s := fmt.Sprintf("(%s)%s:%s", Primary.String(), n.name, n.ws.String()) - if n.http != nil { - s = s + fmt.Sprintf(":%s", n.http.String()) - } - return s -} - -func (n *node[CHAIN_ID, HEAD, RPC]) ConfiguredChainID() (chainID CHAIN_ID) { - return n.chainID -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Name() string { - return n.name -} - -func (n *node[CHAIN_ID, HEAD, RPC]) RPC() RPC { - return n.rpc -} - -// unsubscribeAllExceptAliveLoop is not thread-safe; it should only be called -// while holding the stateMu lock. -func (n *node[CHAIN_ID, HEAD, RPC]) unsubscribeAllExceptAliveLoop() { - n.rpc.UnsubscribeAllExcept(n.healthCheckSubs...) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) UnsubscribeAllExceptAliveLoop() { - n.stateMu.Lock() - defer n.stateMu.Unlock() - n.unsubscribeAllExceptAliveLoop() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Close() error { - return n.StopOnce(n.name, n.close) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) close() error { - defer func() { - n.wg.Wait() - n.rpc.Close() - }() - - n.stateMu.Lock() - defer n.stateMu.Unlock() - - close(n.stopCh) - n.state = NodeStateClosed - return nil -} - -// Start dials and verifies the node -// Should only be called once in a node's lifecycle -// Return value is necessary to conform to interface but this will never -// actually return an error. -func (n *node[CHAIN_ID, HEAD, RPC]) Start(startCtx context.Context) error { - return n.StartOnce(n.name, func() error { - n.start(startCtx) - return nil - }) -} - -// start initially dials the node and verifies chain ID -// This spins off lifecycle goroutines. -// Not thread-safe. -// Node lifecycle is synchronous: only one goroutine should be running at a -// time. -func (n *node[CHAIN_ID, HEAD, RPC]) start(startCtx context.Context) { - if n.state != NodeStateUndialed { - panic(fmt.Sprintf("cannot dial node with state %v", n.state)) - } - - if err := n.rpc.Dial(startCtx); err != nil { - n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err) - n.declareUnreachable() - return - } - n.setState(NodeStateDialed) - - state := n.verifyConn(startCtx, n.lfcLog) - n.declareState(state) -} - -// verifyChainID checks that connection to the node matches the given chain ID -// Not thread-safe -// Pure verifyChainID: does not mutate node "state" field. -func (n *node[CHAIN_ID, HEAD, RPC]) verifyChainID(callerCtx context.Context, lggr logger.Logger) NodeState { - promPoolRPCNodeVerifies.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - promFailed := func() { - promPoolRPCNodeVerifiesFailed.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - } - - st := n.getCachedState() - switch st { - case NodeStateClosed: - // The node is already closed, and any subsequent transition is invalid. - // To make spotting such transitions a bit easier, return the invalid node state. - return NodeStateLen - case NodeStateDialed, NodeStateOutOfSync, NodeStateInvalidChainID, NodeStateSyncing: - default: - panic(fmt.Sprintf("cannot verify node in state %v", st)) - } - - var chainID CHAIN_ID - var err error - if chainID, err = n.rpc.ChainID(callerCtx); err != nil { - promFailed() - lggr.Errorw("Failed to verify chain ID for node", "err", err, "nodeState", n.getCachedState()) - return NodeStateUnreachable - } else if chainID.String() != n.chainID.String() { - promFailed() - err = fmt.Errorf( - "rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s: %w", - chainID.String(), - n.chainID.String(), - n.name, - errInvalidChainID, - ) - lggr.Errorw("Failed to verify RPC node; remote endpoint returned the wrong chain ID", "err", err, "nodeState", n.getCachedState()) - return NodeStateInvalidChainID - } - - promPoolRPCNodeVerifiesSuccess.WithLabelValues(n.chainFamily, n.chainID.String(), n.name).Inc() - - return NodeStateAlive -} - -// createVerifiedConn - establishes new connection with the RPC and verifies that it's valid: chainID matches, and it's not syncing. -// Returns desired state if one of the verifications fails. Otherwise, returns NodeStateAlive. -func (n *node[CHAIN_ID, HEAD, RPC]) createVerifiedConn(ctx context.Context, lggr logger.Logger) NodeState { - if err := n.rpc.Dial(ctx); err != nil { - n.lfcLog.Errorw("Dial failed: Node is unreachable", "err", err, "nodeState", n.getCachedState()) - return NodeStateUnreachable - } - - return n.verifyConn(ctx, lggr) -} - -// verifyConn - verifies that current connection is valid: chainID matches, and it's not syncing. -// Returns desired state if one of the verifications fails. Otherwise, returns NodeStateAlive. -func (n *node[CHAIN_ID, HEAD, RPC]) verifyConn(ctx context.Context, lggr logger.Logger) NodeState { - state := n.verifyChainID(ctx, lggr) - if state != NodeStateAlive { - return state - } - - if n.nodePoolCfg.NodeIsSyncingEnabled() { - isSyncing, err := n.rpc.IsSyncing(ctx) - if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) - return NodeStateUnreachable - } - - if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) - return NodeStateSyncing - } - } - - return NodeStateAlive -} - -func (n *node[CHAIN_ID, HEAD, RPC]) Order() int32 { - return n.order -} - -func (n *node[CHAIN_ID, HEAD, RPC]) newCtx() (context.Context, context.CancelFunc) { - ctx, cancel := n.stopCh.NewCtx() - ctx = CtxAddHealthCheckFlag(ctx) - return ctx, cancel -} diff --git a/pkg/solana/client/multinode/node_fsm.go b/pkg/solana/client/multinode/node_fsm.go deleted file mode 100644 index 136910868..000000000 --- a/pkg/solana/client/multinode/node_fsm.go +++ /dev/null @@ -1,370 +0,0 @@ -package client - -import ( - "fmt" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" -) - -var ( - promPoolRPCNodeTransitionsToAlive = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_alive", - Help: transitionString(NodeStateAlive), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToInSync = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_in_sync", - Help: fmt.Sprintf("%s to %s", transitionString(NodeStateOutOfSync), NodeStateAlive), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToOutOfSync = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_out_of_sync", - Help: transitionString(NodeStateOutOfSync), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToUnreachable = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_unreachable", - Help: transitionString(NodeStateUnreachable), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToInvalidChainID = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_invalid_chain_id", - Help: transitionString(NodeStateInvalidChainID), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToUnusable = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_unusable", - Help: transitionString(NodeStateUnusable), - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeTransitionsToSyncing = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_transitions_to_syncing", - Help: transitionString(NodeStateSyncing), - }, []string{"chainID", "nodeName"}) -) - -// NodeState represents the current state of the node -// Node is a FSM (finite state machine) -type NodeState int - -func (n NodeState) String() string { - switch n { - case NodeStateUndialed: - return "Undialed" - case NodeStateDialed: - return "Dialed" - case NodeStateInvalidChainID: - return "InvalidChainID" - case NodeStateAlive: - return "Alive" - case NodeStateUnreachable: - return "Unreachable" - case NodeStateUnusable: - return "Unusable" - case NodeStateOutOfSync: - return "OutOfSync" - case NodeStateClosed: - return "Closed" - case NodeStateSyncing: - return "Syncing" - case NodeStateFinalizedBlockOutOfSync: - return "FinalizedBlockOutOfSync" - default: - return fmt.Sprintf("NodeState(%d)", n) - } -} - -// GoString prints a prettier state -func (n NodeState) GoString() string { - return fmt.Sprintf("NodeState%s(%d)", n.String(), n) -} - -const ( - // NodeStateUndialed is the first state of a virgin node - NodeStateUndialed = NodeState(iota) - // NodeStateDialed is after a node has successfully dialed but before it has verified the correct chain ID - NodeStateDialed - // NodeStateInvalidChainID is after chain ID verification failed - NodeStateInvalidChainID - // NodeStateAlive is a healthy node after chain ID verification succeeded - NodeStateAlive - // NodeStateUnreachable is a node that cannot be dialed or has disconnected - NodeStateUnreachable - // NodeStateOutOfSync is a node that is accepting connections but exceeded - // the failure threshold without sending any new heads. It will be - // disconnected, then put into a revive loop and re-awakened after redial - // if a new head arrives - NodeStateOutOfSync - // NodeStateUnusable is a sendonly node that has an invalid URL that can never be reached - NodeStateUnusable - // NodeStateClosed is after the connection has been closed and the node is at the end of its lifecycle - NodeStateClosed - // NodeStateSyncing is a node that is actively back-filling blockchain. Usually, it's a newly set up node that is - // still syncing the chain. The main difference from `NodeStateOutOfSync` is that it represents state relative - // to other primary nodes configured in the MultiNode. In contrast, `NodeStateSyncing` represents the internal state of - // the node (RPC). - NodeStateSyncing - // nodeStateFinalizedBlockOutOfSync - node is lagging behind on latest finalized block - NodeStateFinalizedBlockOutOfSync - // nodeStateLen tracks the number of states - NodeStateLen -) - -// allNodeStates represents all possible states a node can be in -var allNodeStates []NodeState - -func init() { - for s := NodeState(0); s < NodeStateLen; s++ { - allNodeStates = append(allNodeStates, s) - } -} - -// FSM methods - -// State allows reading the current state of the node. -func (n *node[CHAIN_ID, HEAD, RPC]) State() NodeState { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - return n.recalculateState() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) getCachedState() NodeState { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - return n.state -} - -func (n *node[CHAIN_ID, HEAD, RPC]) recalculateState() NodeState { - if n.state != NodeStateAlive { - return n.state - } - - // double check that node is not lagging on finalized block - if n.nodePoolCfg.EnforceRepeatableRead() && n.isFinalizedBlockOutOfSync() { - return NodeStateFinalizedBlockOutOfSync - } - - return NodeStateAlive -} - -func (n *node[CHAIN_ID, HEAD, RPC]) isFinalizedBlockOutOfSync() bool { - if n.poolInfoProvider == nil { - return false - } - - highestObservedByCaller := n.poolInfoProvider.HighestUserObservations() - latest, _ := n.rpc.GetInterceptedChainInfo() - if n.chainCfg.FinalityTagEnabled() { - return latest.FinalizedBlockNumber < highestObservedByCaller.FinalizedBlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) - } - - return latest.BlockNumber < highestObservedByCaller.BlockNumber-int64(n.chainCfg.FinalizedBlockOffset()) -} - -// StateAndLatest returns nodeState with the latest ChainInfo observed by Node during current lifecycle. -func (n *node[CHAIN_ID, HEAD, RPC]) StateAndLatest() (NodeState, ChainInfo) { - n.stateMu.RLock() - defer n.stateMu.RUnlock() - latest, _ := n.rpc.GetInterceptedChainInfo() - return n.recalculateState(), latest -} - -// HighestUserObservations - returns highest ChainInfo ever observed by external user of the Node -func (n *node[CHAIN_ID, HEAD, RPC]) HighestUserObservations() ChainInfo { - _, highestUserObservations := n.rpc.GetInterceptedChainInfo() - return highestUserObservations -} -func (n *node[CHAIN_ID, HEAD, RPC]) SetPoolChainInfoProvider(poolInfoProvider PoolChainInfoProvider) { - n.poolInfoProvider = poolInfoProvider -} - -// setState is only used by internal state management methods. -// This is low-level; care should be taken by the caller to ensure the new state is a valid transition. -// State changes should always be synchronous: only one goroutine at a time should change state. -// n.stateMu should not be locked for long periods of time because external clients expect a timely response from n.State() -func (n *node[CHAIN_ID, HEAD, RPC]) setState(s NodeState) { - n.stateMu.Lock() - defer n.stateMu.Unlock() - n.state = s -} - -// declareXXX methods change the state and pass conrol off the new state -// management goroutine - -func (n *node[CHAIN_ID, HEAD, RPC]) declareAlive() { - n.transitionToAlive(func() { - n.lfcLog.Infow("RPC Node is online", "nodeState", n.state) - n.wg.Add(1) - go n.aliveLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToAlive(fn func()) { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateDialed, NodeStateInvalidChainID, NodeStateSyncing: - n.state = NodeStateAlive - default: - panic(transitionFail(n.state, NodeStateAlive)) - } - fn() -} - -// declareInSync puts a node back into Alive state, allowing it to be used by -// pool consumers again -func (n *node[CHAIN_ID, HEAD, RPC]) declareInSync() { - n.transitionToInSync(func() { - n.lfcLog.Infow("RPC Node is back in sync", "nodeState", n.state) - n.wg.Add(1) - go n.aliveLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInSync(fn func()) { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(n.chainID.String(), n.name).Inc() - promPoolRPCNodeTransitionsToInSync.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateOutOfSync, NodeStateSyncing: - n.state = NodeStateAlive - default: - panic(transitionFail(n.state, NodeStateAlive)) - } - fn() -} - -// declareOutOfSync puts a node into OutOfSync state, disconnecting all current -// clients and making it unavailable for use until back in-sync. -func (n *node[CHAIN_ID, HEAD, RPC]) declareOutOfSync(syncIssues syncStatus) { - n.transitionToOutOfSync(func() { - n.lfcLog.Errorw("RPC Node is out of sync", "nodeState", n.state, "syncIssues", syncIssues) - n.wg.Add(1) - go n.outOfSyncLoop(syncIssues) - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToOutOfSync(fn func()) { - promPoolRPCNodeTransitionsToOutOfSync.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateAlive: - n.rpc.Close() - n.state = NodeStateOutOfSync - default: - panic(transitionFail(n.state, NodeStateOutOfSync)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareUnreachable() { - n.transitionToUnreachable(func() { - n.lfcLog.Errorw("RPC Node is unreachable", "nodeState", n.state) - n.wg.Add(1) - go n.unreachableLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToUnreachable(fn func()) { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateUndialed, NodeStateDialed, NodeStateAlive, NodeStateOutOfSync, NodeStateInvalidChainID, NodeStateSyncing: - n.rpc.Close() - n.state = NodeStateUnreachable - default: - panic(transitionFail(n.state, NodeStateUnreachable)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareState(state NodeState) { - if n.getCachedState() == NodeStateClosed { - return - } - switch state { - case NodeStateInvalidChainID: - n.declareInvalidChainID() - case NodeStateUnreachable: - n.declareUnreachable() - case NodeStateSyncing: - n.declareSyncing() - case NodeStateAlive: - n.declareAlive() - default: - panic(fmt.Sprintf("%#v state declaration is not implemented", state)) - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareInvalidChainID() { - n.transitionToInvalidChainID(func() { - n.lfcLog.Errorw("RPC Node has the wrong chain ID", "nodeState", n.state) - n.wg.Add(1) - go n.invalidChainIDLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToInvalidChainID(fn func()) { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateDialed, NodeStateOutOfSync, NodeStateSyncing: - n.rpc.Close() - n.state = NodeStateInvalidChainID - default: - panic(transitionFail(n.state, NodeStateInvalidChainID)) - } - fn() -} - -func (n *node[CHAIN_ID, HEAD, RPC]) declareSyncing() { - n.transitionToSyncing(func() { - n.lfcLog.Errorw("RPC Node is syncing", "nodeState", n.state) - n.wg.Add(1) - go n.syncingLoop() - }) -} - -func (n *node[CHAIN_ID, HEAD, RPC]) transitionToSyncing(fn func()) { - promPoolRPCNodeTransitionsToSyncing.WithLabelValues(n.chainID.String(), n.name).Inc() - n.stateMu.Lock() - defer n.stateMu.Unlock() - if n.state == NodeStateClosed { - return - } - switch n.state { - case NodeStateDialed, NodeStateOutOfSync, NodeStateInvalidChainID: - n.rpc.Close() - n.state = NodeStateSyncing - default: - panic(transitionFail(n.state, NodeStateSyncing)) - } - - if !n.nodePoolCfg.NodeIsSyncingEnabled() { - panic("unexpected transition to NodeStateSyncing, while it's disabled") - } - fn() -} - -func transitionString(state NodeState) string { - return fmt.Sprintf("Total number of times node has transitioned to %s", state) -} - -func transitionFail(from NodeState, to NodeState) string { - return fmt.Sprintf("cannot transition from %#v to %#v", from, to) -} diff --git a/pkg/solana/client/multinode/node_lifecycle.go b/pkg/solana/client/multinode/node_lifecycle.go deleted file mode 100644 index bca637a22..000000000 --- a/pkg/solana/client/multinode/node_lifecycle.go +++ /dev/null @@ -1,697 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math" - "math/big" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils" - bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" -) - -var ( - promPoolRPCNodeHighestSeenBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "solana_pool_rpc_node_highest_seen_block", - Help: "The highest seen block for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeHighestFinalizedBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "solana_pool_rpc_node_highest_finalized_block", - Help: "The highest seen finalized block for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodeNumSeenBlocks = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_num_seen_blocks", - Help: "The total number of new blocks seen by the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePolls = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_polls_total", - Help: "The total number of poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePollsFailed = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_polls_failed", - Help: "The total number of failed poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) - promPoolRPCNodePollsSuccess = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_pool_rpc_node_polls_success", - Help: "The total number of successful poll checks for the given RPC node", - }, []string{"chainID", "nodeName"}) -) - -// zombieNodeCheckInterval controls how often to re-check to see if we need to -// state change in case we have to force a state transition due to no available -// nodes. -// NOTE: This only applies to out-of-sync nodes if they are the last available node -func zombieNodeCheckInterval(noNewHeadsThreshold time.Duration) time.Duration { - interval := noNewHeadsThreshold - if interval <= 0 || interval > QueryTimeout { - interval = QueryTimeout - } - return utils.WithJitter(interval) -} - -const ( - msgCannotDisable = "but cannot disable this connection because there are no other RPC endpoints, or all other RPC endpoints are dead." - msgDegradedState = "Chainlink is now operating in a degraded state and urgent action is required to resolve the issue" -) - -// Node is a FSM -// Each state has a loop that goes with it, which monitors the node and moves it into another state as necessary. -// Only one loop must run at a time. -// Each loop passes control onto the next loop as it exits, except when the node is Closed which terminates the loop permanently. - -// This handles node lifecycle for the ALIVE state -// Should only be run ONCE per node, after a successful Dial -func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case NodeStateAlive: - case NodeStateClosed: - return - default: - panic(fmt.Sprintf("aliveLoop can only run for node in Alive state, got: %s", state)) - } - } - - noNewHeadsTimeoutThreshold := n.chainCfg.NodeNoNewHeadsThreshold() - noNewFinalizedBlocksTimeoutThreshold := n.chainCfg.NoNewFinalizedHeadsThreshold() - pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold() - pollInterval := n.nodePoolCfg.PollInterval() - - lggr := logger.Sugared(n.lfcLog).Named("Alive").With("noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold, "pollInterval", pollInterval, "pollFailureThreshold", pollFailureThreshold) - lggr.Tracew("Alive loop starting", "nodeState", n.getCachedState()) - - headsSub, err := n.registerNewSubscription(ctx, lggr.With("subscriptionType", "heads"), - n.chainCfg.NodeNoNewHeadsThreshold(), n.rpc.SubscribeToHeads) - if err != nil { - lggr.Errorw("Initial subscribe for heads failed", "nodeState", n.getCachedState(), "err", err) - n.declareUnreachable() - return - } - - defer n.unsubscribeHealthChecks() - - var pollCh <-chan time.Time - if pollInterval > 0 { - lggr.Debug("Polling enabled") - pollT := time.NewTicker(pollInterval) - defer pollT.Stop() - pollCh = pollT.C - if pollFailureThreshold > 0 { - // polling can be enabled with no threshold to enable polling but - // the node will not be marked offline regardless of the number of - // poll failures - lggr.Debug("Polling liveness checking enabled") - } - } else { - lggr.Debug("Polling disabled") - } - - var finalizedHeadsSub headSubscription[HEAD] - if n.chainCfg.FinalityTagEnabled() { - finalizedHeadsSub, err = n.registerNewSubscription(ctx, lggr.With("subscriptionType", "finalizedHeads"), - n.chainCfg.NoNewFinalizedHeadsThreshold(), n.rpc.SubscribeToFinalizedHeads) - if err != nil { - lggr.Errorw("Failed to subscribe to finalized heads", "err", err) - n.declareUnreachable() - return - } - } - - // Get the latest chain info to use as local highest - localHighestChainInfo, _ := n.rpc.GetInterceptedChainInfo() - var pollFailures uint32 - - for { - select { - case <-ctx.Done(): - return - case <-pollCh: - promPoolRPCNodePolls.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Tracew("Pinging RPC", "nodeState", n.State(), "pollFailures", pollFailures) - pollCtx, cancel := context.WithTimeout(ctx, pollInterval) - err = n.RPC().Ping(pollCtx) - cancel() - if err != nil { - // prevent overflow - if pollFailures < math.MaxUint32 { - promPoolRPCNodePollsFailed.WithLabelValues(n.chainID.String(), n.name).Inc() - pollFailures++ - } - lggr.Warnw(fmt.Sprintf("Poll failure, RPC endpoint %s failed to respond properly", n.String()), "err", err, "pollFailures", pollFailures, "nodeState", n.getCachedState()) - } else { - lggr.Debugw("Ping successful", "nodeState", n.State()) - promPoolRPCNodePollsSuccess.WithLabelValues(n.chainID.String(), n.name).Inc() - pollFailures = 0 - } - if pollFailureThreshold > 0 && pollFailures >= pollFailureThreshold { - lggr.Errorw(fmt.Sprintf("RPC endpoint failed to respond to %d consecutive polls", pollFailures), "pollFailures", pollFailures, "nodeState", n.getCachedState()) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC endpoint failed to respond to polls; %s %s", msgCannotDisable, msgDegradedState) - continue - } - } - n.declareUnreachable() - return - } - if outOfSync, liveNodes := n.isOutOfSyncWithPool(); outOfSync { - // note: there must be another live node for us to be out of sync - if liveNodes < 2 { - lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) - continue - } - n.declareOutOfSync(syncStatusNotInSyncWithPool) - return - } - case bh, open := <-headsSub.Heads: - if !open { - lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - receivedNewHead := n.onNewHead(lggr, &localHighestChainInfo, bh) - if receivedNewHead && noNewHeadsTimeoutThreshold > 0 { - headsSub.ResetTimer(noNewHeadsTimeoutThreshold) - } - case err = <-headsSub.Errors: - lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.getCachedState()) - n.declareUnreachable() - return - case <-headsSub.NoNewHeads: - // We haven't received a head on the channel for at least the - // threshold amount of time, mark it broken - lggr.Errorw(fmt.Sprintf("RPC endpoint detected out of sync; no new heads received for %s (last head received was %v)", noNewHeadsTimeoutThreshold, localHighestChainInfo.BlockNumber), "nodeState", n.getCachedState(), "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber, "noNewHeadsTimeoutThreshold", noNewHeadsTimeoutThreshold) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) - // We don't necessarily want to wait the full timeout to check again, we should - // check regularly and log noisily in this state - headsSub.ResetTimer(zombieNodeCheckInterval(noNewHeadsTimeoutThreshold)) - continue - } - } - n.declareOutOfSync(syncStatusNoNewHead) - return - case latestFinalized, open := <-finalizedHeadsSub.Heads: - if !open { - lggr.Errorw("Finalized heads subscription channel unexpectedly closed") - n.declareUnreachable() - return - } - - receivedNewHead := n.onNewFinalizedHead(lggr, &localHighestChainInfo, latestFinalized) - if receivedNewHead && noNewFinalizedBlocksTimeoutThreshold > 0 { - finalizedHeadsSub.ResetTimer(noNewFinalizedBlocksTimeoutThreshold) - } - case <-finalizedHeadsSub.NoNewHeads: - // We haven't received a finalized head on the channel for at least the - // threshold amount of time, mark it broken - lggr.Errorw(fmt.Sprintf("RPC's finalized state is out of sync; no new finalized heads received for %s (last finalized head received was %v)", noNewFinalizedBlocksTimeoutThreshold, localHighestChainInfo.FinalizedBlockNumber), "latestReceivedBlockNumber", localHighestChainInfo.BlockNumber) - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 2 { - lggr.Criticalf("RPC's finalized state is out of sync; %s %s", msgCannotDisable, msgDegradedState) - // We don't necessarily want to wait the full timeout to check again, we should - // check regularly and log noisily in this state - finalizedHeadsSub.ResetTimer(zombieNodeCheckInterval(noNewFinalizedBlocksTimeoutThreshold)) - continue - } - } - n.declareOutOfSync(syncStatusNoNewFinalizedHead) - return - case <-finalizedHeadsSub.Errors: - lggr.Errorw("Finalized heads subscription was terminated", "err", err) - n.declareUnreachable() - return - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) unsubscribeHealthChecks() { - n.stateMu.Lock() - for _, sub := range n.healthCheckSubs { - sub.Unsubscribe() - } - n.healthCheckSubs = []Subscription{} - n.stateMu.Unlock() -} - -type headSubscription[HEAD any] struct { - Heads <-chan HEAD - Errors <-chan error - NoNewHeads <-chan time.Time - - noNewHeadsTicker *time.Ticker - sub Subscription - cleanUpTasks []func() -} - -func (sub *headSubscription[HEAD]) ResetTimer(duration time.Duration) { - sub.noNewHeadsTicker.Reset(duration) -} - -func (sub *headSubscription[HEAD]) Unsubscribe() { - for _, doCleanUp := range sub.cleanUpTasks { - doCleanUp() - } -} - -func (n *node[CHAIN_ID, HEAD, PRC]) registerNewSubscription(ctx context.Context, lggr logger.SugaredLogger, - noNewDataThreshold time.Duration, newSub func(ctx context.Context) (<-chan HEAD, Subscription, error)) (headSubscription[HEAD], error) { - result := headSubscription[HEAD]{} - var err error - var sub Subscription - result.Heads, sub, err = newSub(ctx) - if err != nil { - return result, err - } - - result.Errors = sub.Err() - lggr.Debug("Successfully subscribed") - - result.sub = sub - n.stateMu.Lock() - n.healthCheckSubs = append(n.healthCheckSubs, sub) - n.stateMu.Unlock() - - result.cleanUpTasks = append(result.cleanUpTasks, sub.Unsubscribe) - - if noNewDataThreshold > 0 { - lggr.Debugw("Subscription liveness checking enabled") - result.noNewHeadsTicker = time.NewTicker(noNewDataThreshold) - result.NoNewHeads = result.noNewHeadsTicker.C - result.cleanUpTasks = append(result.cleanUpTasks, result.noNewHeadsTicker.Stop) - } else { - lggr.Debug("Subscription liveness checking disabled") - } - - return result, nil -} - -func (n *node[CHAIN_ID, HEAD, RPC]) onNewFinalizedHead(lggr logger.SugaredLogger, chainInfo *ChainInfo, latestFinalized HEAD) bool { - if !latestFinalized.IsValid() { - lggr.Warn("Latest finalized block is not valid") - return false - } - - latestFinalizedBN := latestFinalized.BlockNumber() - lggr.Debugw("Got latest finalized head", "latestFinalized", latestFinalized) - if latestFinalizedBN <= chainInfo.FinalizedBlockNumber { - lggr.Debugw("Ignoring previously seen finalized block number") - return false - } - - promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - chainInfo.FinalizedBlockNumber = latestFinalizedBN - return true -} - -func (n *node[CHAIN_ID, HEAD, RPC]) onNewHead(lggr logger.SugaredLogger, chainInfo *ChainInfo, head HEAD) bool { - if !head.IsValid() { - lggr.Warn("Latest head is not valid") - return false - } - - promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Debugw("Got head", "head", head) - lggr = lggr.With("latestReceivedBlockNumber", chainInfo.BlockNumber, "blockNumber", head.BlockNumber(), "nodeState", n.getCachedState()) - if head.BlockNumber() <= chainInfo.BlockNumber { - lggr.Debugw("Ignoring previously seen block number") - return false - } - - promPoolRPCNodeHighestSeenBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(head.BlockNumber())) - chainInfo.BlockNumber = head.BlockNumber() - - if !n.chainCfg.FinalityTagEnabled() { - latestFinalizedBN := max(head.BlockNumber()-int64(n.chainCfg.FinalityDepth()), 0) - if latestFinalizedBN > chainInfo.FinalizedBlockNumber { - promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) - chainInfo.FinalizedBlockNumber = latestFinalizedBN - } - } - - return true -} - -const ( - msgReceivedBlock = "Received block for RPC node, waiting until back in-sync to mark as live again" - msgReceivedFinalizedBlock = "Received new finalized block for RPC node, waiting until back in-sync to mark as live again" - msgInSync = "RPC node back in sync" -) - -// isOutOfSyncWithPool returns outOfSync true if num or td is more than SyncThresold behind the best node. -// Always returns outOfSync false for SyncThreshold 0. -// liveNodes is only included when outOfSync is true. -func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool() (outOfSync bool, liveNodes int) { - if n.poolInfoProvider == nil { - n.lfcLog.Warn("skipping sync state against the pool - should only occur in tests") - return // skip for tests - } - threshold := n.nodePoolCfg.SyncThreshold() - if threshold == 0 { - return // disabled - } - // Check against best node - ln, ci := n.poolInfoProvider.LatestChainInfo() - localChainInfo, _ := n.rpc.GetInterceptedChainInfo() - mode := n.nodePoolCfg.SelectionMode() - switch mode { - case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel: - outOfSync = localChainInfo.BlockNumber < ci.BlockNumber-int64(threshold) - case NodeSelectionModeTotalDifficulty: - bigThreshold := big.NewInt(int64(threshold)) - outOfSync = localChainInfo.TotalDifficulty.Cmp(bigmath.Sub(ci.TotalDifficulty, bigThreshold)) < 0 - default: - panic("unrecognized NodeSelectionMode: " + mode) - } - - if outOfSync && n.getCachedState() == NodeStateAlive { - n.lfcLog.Errorw("RPC endpoint has fallen behind", "blockNumber", localChainInfo.BlockNumber, "bestLatestBlockNumber", ci.BlockNumber, "totalDifficulty", localChainInfo.TotalDifficulty) - } - return outOfSync, ln -} - -// outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status -func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case NodeStateOutOfSync: - case NodeStateClosed: - return - default: - panic(fmt.Sprintf("outOfSyncLoop can only run for node in OutOfSync state, got: %s", state)) - } - } - - outOfSyncAt := time.Now() - - // set logger name to OutOfSync or FinalizedBlockOutOfSync - lggr := logger.Sugared(logger.Named(n.lfcLog, n.getCachedState().String())).With("nodeState", n.getCachedState()) - lggr.Debugw("Trying to revive out-of-sync RPC node") - - // Need to redial since out-of-sync nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != NodeStateAlive { - n.declareState(state) - return - } - - noNewHeadsTimeoutThreshold := n.chainCfg.NodeNoNewHeadsThreshold() - headsSub, err := n.registerNewSubscription(ctx, lggr.With("subscriptionType", "heads"), - noNewHeadsTimeoutThreshold, n.rpc.SubscribeToHeads) - if err != nil { - lggr.Errorw("Failed to subscribe heads on out-of-sync RPC node", "err", err) - n.declareUnreachable() - return - } - - defer n.unsubscribeHealthChecks() - - lggr.Tracew("Successfully subscribed to heads feed on out-of-sync RPC node") - - noNewFinalizedBlocksTimeoutThreshold := n.chainCfg.NoNewFinalizedHeadsThreshold() - var finalizedHeadsSub headSubscription[HEAD] - if n.chainCfg.FinalityTagEnabled() { - finalizedHeadsSub, err = n.registerNewSubscription(ctx, lggr.With("subscriptionType", "finalizedHeads"), - noNewFinalizedBlocksTimeoutThreshold, n.rpc.SubscribeToFinalizedHeads) - if err != nil { - lggr.Errorw("Subscribe to finalized heads failed on out-of-sync RPC node", "err", err) - n.declareUnreachable() - return - } - - lggr.Tracew("Successfully subscribed to finalized heads feed on out-of-sync RPC node") - } - - _, localHighestChainInfo := n.rpc.GetInterceptedChainInfo() - for { - if syncIssues == syncStatusSynced { - // back in-sync! flip back into alive loop - lggr.Infow(fmt.Sprintf("%s: %s. Node was out-of-sync for %s", msgInSync, n.String(), time.Since(outOfSyncAt))) - n.declareInSync() - return - } - - select { - case <-ctx.Done(): - return - case head, open := <-headsSub.Heads: - if !open { - lggr.Errorw("Subscription channel unexpectedly closed", "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - - if !n.onNewHead(lggr, &localHighestChainInfo, head) { - continue - } - - // received a new head - clear NoNewHead flag - syncIssues &= ^syncStatusNoNewHead - if outOfSync, _ := n.isOutOfSyncWithPool(); !outOfSync { - // we caught up with the pool - clear NotInSyncWithPool flag - syncIssues &= ^syncStatusNotInSyncWithPool - } else { - // we've received new head, but lagging behind the pool, add NotInSyncWithPool flag to prevent false transition to alive - syncIssues |= syncStatusNotInSyncWithPool - } - - if noNewHeadsTimeoutThreshold > 0 { - headsSub.ResetTimer(noNewHeadsTimeoutThreshold) - } - - lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "syncIssues", syncIssues) - case <-time.After(zombieNodeCheckInterval(noNewHeadsTimeoutThreshold)): - if n.poolInfoProvider != nil { - if l, _ := n.poolInfoProvider.LatestChainInfo(); l < 1 { - lggr.Criticalw("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state", "syncIssues", syncIssues) - n.declareInSync() - return - } - } - case err := <-headsSub.Errors: - lggr.Errorw("Subscription was terminated", "err", err) - n.declareUnreachable() - return - case <-headsSub.NoNewHeads: - // we are not resetting the timer, as there is no need to add syncStatusNoNewHead until it's removed on new head. - syncIssues |= syncStatusNoNewHead - lggr.Debugw(fmt.Sprintf("No new heads received for %s. Node stays out-of-sync due to sync issues: %s", noNewHeadsTimeoutThreshold, syncIssues)) - case latestFinalized, open := <-finalizedHeadsSub.Heads: - if !open { - lggr.Errorw("Finalized heads subscription channel unexpectedly closed") - n.declareUnreachable() - return - } - if !latestFinalized.IsValid() { - lggr.Warn("Latest finalized block is not valid") - continue - } - - receivedNewHead := n.onNewFinalizedHead(lggr, &localHighestChainInfo, latestFinalized) - if !receivedNewHead { - continue - } - - // on new finalized head remove NoNewFinalizedHead flag from the mask - syncIssues &= ^syncStatusNoNewFinalizedHead - if noNewFinalizedBlocksTimeoutThreshold > 0 { - finalizedHeadsSub.ResetTimer(noNewFinalizedBlocksTimeoutThreshold) - } - - var highestSeen ChainInfo - if n.poolInfoProvider != nil { - highestSeen = n.poolInfoProvider.HighestUserObservations() - } - - lggr.Debugw(msgReceivedFinalizedBlock, "blockNumber", latestFinalized.BlockNumber(), "poolHighestBlockNumber", highestSeen.FinalizedBlockNumber, "syncIssues", syncIssues) - case err := <-finalizedHeadsSub.Errors: - lggr.Errorw("Finalized head subscription was terminated", "err", err) - n.declareUnreachable() - return - case <-finalizedHeadsSub.NoNewHeads: - // we are not resetting the timer, as there is no need to add syncStatusNoNewFinalizedHead until it's removed on new finalized head. - syncIssues |= syncStatusNoNewFinalizedHead - lggr.Debugw(fmt.Sprintf("No new finalized heads received for %s. Node stays out-of-sync due to sync issues: %s", noNewFinalizedBlocksTimeoutThreshold, syncIssues)) - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) unreachableLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case NodeStateUnreachable: - case NodeStateClosed: - return - default: - panic(fmt.Sprintf("unreachableLoop can only run for node in Unreachable state, got: %s", state)) - } - } - - unreachableAt := time.Now() - - lggr := logger.Sugared(logger.Named(n.lfcLog, "Unreachable")) - lggr.Debugw("Trying to revive unreachable RPC node", "nodeState", n.getCachedState()) - - dialRetryBackoff := NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(dialRetryBackoff.Duration()): - lggr.Tracew("Trying to re-dial RPC node", "nodeState", n.getCachedState()) - - err := n.rpc.Dial(ctx) - if err != nil { - lggr.Errorw(fmt.Sprintf("Failed to redial RPC node; still unreachable: %v", err), "err", err, "nodeState", n.getCachedState()) - continue - } - - n.setState(NodeStateDialed) - - state := n.verifyConn(ctx, lggr) - switch state { - case NodeStateUnreachable: - n.setState(NodeStateUnreachable) - continue - case NodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully redialled and verified RPC node %s. Node was offline for %s", n.String(), time.Since(unreachableAt)), "nodeState", n.getCachedState()) - fallthrough - default: - n.declareState(state) - return - } - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) invalidChainIDLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case NodeStateInvalidChainID: - case NodeStateClosed: - return - default: - panic(fmt.Sprintf("invalidChainIDLoop can only run for node in InvalidChainID state, got: %s", state)) - } - } - - invalidAt := time.Now() - - lggr := logger.Named(n.lfcLog, "InvalidChainID") - - // Need to redial since invalid chain ID nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != NodeStateInvalidChainID { - n.declareState(state) - return - } - - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with invalid chain ID", n.String()), "nodeState", n.getCachedState()) - - chainIDRecheckBackoff := NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(chainIDRecheckBackoff.Duration()): - state := n.verifyConn(ctx, lggr) - switch state { - case NodeStateInvalidChainID: - continue - case NodeStateAlive: - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was offline for %s", time.Since(invalidAt)), "nodeState", n.getCachedState()) - fallthrough - default: - n.declareState(state) - return - } - } - } -} - -func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { - defer n.wg.Done() - ctx, cancel := n.newCtx() - defer cancel() - - { - // sanity check - state := n.getCachedState() - switch state { - case NodeStateSyncing: - case NodeStateClosed: - return - default: - panic(fmt.Sprintf("syncingLoop can only run for node in NodeStateSyncing state, got: %s", state)) - } - } - - syncingAt := time.Now() - - lggr := logger.Sugared(logger.Named(n.lfcLog, "Syncing")) - lggr.Debugw(fmt.Sprintf("Periodically re-checking RPC node %s with syncing status", n.String()), "nodeState", n.getCachedState()) - // Need to redial since syncing nodes are automatically disconnected - state := n.createVerifiedConn(ctx, lggr) - if state != NodeStateSyncing { - n.declareState(state) - return - } - - recheckBackoff := NewRedialBackoff() - - for { - select { - case <-ctx.Done(): - return - case <-time.After(recheckBackoff.Duration()): - lggr.Tracew("Trying to recheck if the node is still syncing", "nodeState", n.getCachedState()) - isSyncing, err := n.rpc.IsSyncing(ctx) - if err != nil { - lggr.Errorw("Unexpected error while verifying RPC node synchronization status", "err", err, "nodeState", n.getCachedState()) - n.declareUnreachable() - return - } - - if isSyncing { - lggr.Errorw("Verification failed: Node is syncing", "nodeState", n.getCachedState()) - continue - } - - lggr.Infow(fmt.Sprintf("Successfully verified RPC node. Node was syncing for %s", time.Since(syncingAt)), "nodeState", n.getCachedState()) - n.declareAlive() - return - } - } -} diff --git a/pkg/solana/client/multinode/node_selector.go b/pkg/solana/client/multinode/node_selector.go deleted file mode 100644 index 872026fe2..000000000 --- a/pkg/solana/client/multinode/node_selector.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - "fmt" -) - -const ( - NodeSelectionModeHighestHead = "HighestHead" - NodeSelectionModeRoundRobin = "RoundRobin" - NodeSelectionModeTotalDifficulty = "TotalDifficulty" - NodeSelectionModePriorityLevel = "PriorityLevel" -) - -type NodeSelector[ - CHAIN_ID ID, - RPC any, -] interface { - // Select returns a Node, or nil if none can be selected. - // Implementation must be thread-safe. - Select() Node[CHAIN_ID, RPC] - // Name returns the strategy name, e.g. "HighestHead" or "RoundRobin" - Name() string -} - -func newNodeSelector[ - CHAIN_ID ID, - RPC any, -](selectionMode string, nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - switch selectionMode { - case NodeSelectionModeHighestHead: - return NewHighestHeadNodeSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModeRoundRobin: - return NewRoundRobinSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModeTotalDifficulty: - return NewTotalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) - case NodeSelectionModePriorityLevel: - return NewPriorityLevelNodeSelector[CHAIN_ID, RPC](nodes) - default: - panic(fmt.Sprintf("unsupported NodeSelectionMode: %s", selectionMode)) - } -} diff --git a/pkg/solana/client/multinode/node_selector_highest_head.go b/pkg/solana/client/multinode/node_selector_highest_head.go deleted file mode 100644 index 68901cba3..000000000 --- a/pkg/solana/client/multinode/node_selector_highest_head.go +++ /dev/null @@ -1,36 +0,0 @@ -package client - -import "math" - -type highestHeadNodeSelector[ - CHAIN_ID ID, - RPC any, -] []Node[CHAIN_ID, RPC] - -func NewHighestHeadNodeSelector[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return highestHeadNodeSelector[CHAIN_ID, RPC](nodes) -} - -func (s highestHeadNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - var highestHeadNumber int64 = math.MinInt64 - var highestHeadNodes []Node[CHAIN_ID, RPC] - for _, n := range s { - state, currentChainInfo := n.StateAndLatest() - currentHeadNumber := currentChainInfo.BlockNumber - if state == NodeStateAlive && currentHeadNumber >= highestHeadNumber { - if highestHeadNumber < currentHeadNumber { - highestHeadNumber = currentHeadNumber - highestHeadNodes = nil - } - highestHeadNodes = append(highestHeadNodes, n) - } - } - return firstOrHighestPriority(highestHeadNodes) -} - -func (s highestHeadNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeHighestHead -} diff --git a/pkg/solana/client/multinode/node_selector_priority_level.go b/pkg/solana/client/multinode/node_selector_priority_level.go deleted file mode 100644 index ead720976..000000000 --- a/pkg/solana/client/multinode/node_selector_priority_level.go +++ /dev/null @@ -1,121 +0,0 @@ -package client - -import ( - "math" - "sort" - "sync/atomic" -) - -type priorityLevelNodeSelector[ - CHAIN_ID ID, - RPC any, -] struct { - nodes []Node[CHAIN_ID, RPC] - roundRobinCount []atomic.Uint32 -} - -type nodeWithPriority[ - CHAIN_ID ID, - RPC any, -] struct { - node Node[CHAIN_ID, RPC] - priority int32 -} - -func NewPriorityLevelNodeSelector[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return &priorityLevelNodeSelector[CHAIN_ID, RPC]{ - nodes: nodes, - roundRobinCount: make([]atomic.Uint32, nrOfPriorityTiers(nodes)), - } -} - -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - nodes := s.getHighestPriorityAliveTier() - - if len(nodes) == 0 { - return nil - } - priorityLevel := nodes[len(nodes)-1].priority - - // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter - count := int(s.roundRobinCount[priorityLevel].Add(1) - 1) - idx := count % len(nodes) - - return nodes[idx].node -} - -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModePriorityLevel -} - -// getHighestPriorityAliveTier filters nodes that are not in state NodeStateAlive and -// returns only the highest tier of alive nodes -func (s priorityLevelNodeSelector[CHAIN_ID, RPC]) getHighestPriorityAliveTier() []nodeWithPriority[CHAIN_ID, RPC] { - var nodes []nodeWithPriority[CHAIN_ID, RPC] - for _, n := range s.nodes { - if n.State() == NodeStateAlive { - nodes = append(nodes, nodeWithPriority[CHAIN_ID, RPC]{n, n.Order()}) - } - } - - if len(nodes) == 0 { - return nil - } - - return removeLowerTiers(nodes) -} - -// removeLowerTiers take a slice of nodeWithPriority[CHAIN_ID, BLOCK_HASH, HEAD, RPC] and keeps only the highest tier -func removeLowerTiers[ - CHAIN_ID ID, - RPC any, -](nodes []nodeWithPriority[CHAIN_ID, RPC]) []nodeWithPriority[CHAIN_ID, RPC] { - sort.SliceStable(nodes, func(i, j int) bool { - return nodes[i].priority > nodes[j].priority - }) - - var nodes2 []nodeWithPriority[CHAIN_ID, RPC] - currentPriority := nodes[len(nodes)-1].priority - - for _, n := range nodes { - if n.priority == currentPriority { - nodes2 = append(nodes2, n) - } - } - - return nodes2 -} - -// nrOfPriorityTiers calculates the total number of priority tiers -func nrOfPriorityTiers[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) int32 { - highestPriority := int32(0) - for _, n := range nodes { - priority := n.Order() - if highestPriority < priority { - highestPriority = priority - } - } - return highestPriority + 1 -} - -// firstOrHighestPriority takes a list of nodes and returns the first one with the highest priority -func firstOrHighestPriority[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) Node[CHAIN_ID, RPC] { - hp := int32(math.MaxInt32) - var node Node[CHAIN_ID, RPC] - for _, n := range nodes { - if n.Order() < hp { - hp = n.Order() - node = n - } - } - return node -} diff --git a/pkg/solana/client/multinode/node_selector_round_robin.go b/pkg/solana/client/multinode/node_selector_round_robin.go deleted file mode 100644 index c5ed8d853..000000000 --- a/pkg/solana/client/multinode/node_selector_round_robin.go +++ /dev/null @@ -1,46 +0,0 @@ -package client - -import ( - "sync/atomic" -) - -type roundRobinSelector[ - CHAIN_ID ID, - RPC any, -] struct { - nodes []Node[CHAIN_ID, RPC] - roundRobinCount atomic.Uint32 -} - -func NewRoundRobinSelector[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return &roundRobinSelector[CHAIN_ID, RPC]{ - nodes: nodes, - } -} - -func (s *roundRobinSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - var liveNodes []Node[CHAIN_ID, RPC] - for _, n := range s.nodes { - if n.State() == NodeStateAlive { - liveNodes = append(liveNodes, n) - } - } - - nNodes := len(liveNodes) - if nNodes == 0 { - return nil - } - - // NOTE: Inc returns the number after addition, so we must -1 to get the "current" counter - count := int(s.roundRobinCount.Add(1) - 1) - idx := count % nNodes - - return liveNodes[idx] -} - -func (s *roundRobinSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeRoundRobin -} diff --git a/pkg/solana/client/multinode/node_selector_total_difficulty.go b/pkg/solana/client/multinode/node_selector_total_difficulty.go deleted file mode 100644 index 3f3c79de9..000000000 --- a/pkg/solana/client/multinode/node_selector_total_difficulty.go +++ /dev/null @@ -1,51 +0,0 @@ -package client - -import ( - "math/big" -) - -type totalDifficultyNodeSelector[ - CHAIN_ID ID, - RPC any, -] []Node[CHAIN_ID, RPC] - -func NewTotalDifficultyNodeSelector[ - CHAIN_ID ID, - RPC any, -](nodes []Node[CHAIN_ID, RPC]) NodeSelector[CHAIN_ID, RPC] { - return totalDifficultyNodeSelector[CHAIN_ID, RPC](nodes) -} - -func (s totalDifficultyNodeSelector[CHAIN_ID, RPC]) Select() Node[CHAIN_ID, RPC] { - // NodeNoNewHeadsThreshold may not be enabled, in this case all nodes have td == nil - var highestTD *big.Int - var nodes []Node[CHAIN_ID, RPC] - var aliveNodes []Node[CHAIN_ID, RPC] - - for _, n := range s { - state, currentChainInfo := n.StateAndLatest() - if state != NodeStateAlive { - continue - } - - currentTD := currentChainInfo.TotalDifficulty - aliveNodes = append(aliveNodes, n) - if currentTD != nil && (highestTD == nil || currentTD.Cmp(highestTD) >= 0) { - if highestTD == nil || currentTD.Cmp(highestTD) > 0 { - highestTD = currentTD - nodes = nil - } - nodes = append(nodes, n) - } - } - - //If all nodes have td == nil pick one from the nodes that are alive - if len(nodes) == 0 { - return firstOrHighestPriority(aliveNodes) - } - return firstOrHighestPriority(nodes) -} - -func (s totalDifficultyNodeSelector[CHAIN_ID, RPC]) Name() string { - return NodeSelectionModeTotalDifficulty -} diff --git a/pkg/solana/client/multinode/poller.go b/pkg/solana/client/multinode/poller.go deleted file mode 100644 index 0ce87fade..000000000 --- a/pkg/solana/client/multinode/poller.go +++ /dev/null @@ -1,93 +0,0 @@ -package client - -import ( - "context" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -// Poller is a component that polls a function at a given interval -// and delivers the result to a channel. It is used by multinode to poll -// for new heads and implements the Subscription interface. -type Poller[T any] struct { - services.Service - eng *services.Engine - - pollingInterval time.Duration - pollingFunc func(ctx context.Context) (T, error) - pollingTimeout time.Duration - channel chan<- T - errCh chan error -} - -// NewPoller creates a new Poller instance and returns a channel to receive the polled data -func NewPoller[ - T any, -](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, lggr logger.Logger) (Poller[T], <-chan T) { - channel := make(chan T) - p := Poller[T]{ - pollingInterval: pollingInterval, - pollingFunc: pollingFunc, - pollingTimeout: pollingTimeout, - channel: channel, - errCh: make(chan error), - } - p.Service, p.eng = services.Config{ - Name: "Poller", - Start: p.start, - Close: p.close, - }.NewServiceEngine(lggr) - return p, channel -} - -var _ Subscription = &Poller[any]{} - -func (p *Poller[T]) start(ctx context.Context) error { - p.eng.Go(p.pollingLoop) - return nil -} - -// Unsubscribe cancels the sending of events to the data channel -func (p *Poller[T]) Unsubscribe() { - _ = p.Close() -} - -func (p *Poller[T]) close() error { - close(p.errCh) - close(p.channel) - return nil -} - -func (p *Poller[T]) Err() <-chan error { - return p.errCh -} - -func (p *Poller[T]) pollingLoop(ctx context.Context) { - ticker := services.NewTicker(p.pollingInterval) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - // Set polling timeout - pollingCtx, cancelPolling := context.WithTimeout(ctx, p.pollingTimeout) - // Execute polling function - result, err := p.pollingFunc(pollingCtx) - cancelPolling() - if err != nil { - p.eng.Warnf("polling error: %v", err) - continue - } - // Send result to channel or block if channel is full - select { - case p.channel <- result: - case <-ctx.Done(): - return - } - } - } -} diff --git a/pkg/solana/client/multinode/redialbackoff.go b/pkg/solana/client/multinode/redialbackoff.go deleted file mode 100644 index 41be2232d..000000000 --- a/pkg/solana/client/multinode/redialbackoff.go +++ /dev/null @@ -1,17 +0,0 @@ -package client - -import ( - "time" - - "github.com/jpillora/backoff" -) - -// NewRedialBackoff is a standard backoff to use for redialling or reconnecting to -// unreachable network endpoints -func NewRedialBackoff() backoff.Backoff { - return backoff.Backoff{ - Min: 1 * time.Second, - Max: 15 * time.Second, - Jitter: true, - } -} diff --git a/pkg/solana/client/multinode/send_only_node.go b/pkg/solana/client/multinode/send_only_node.go deleted file mode 100644 index 4f60f566d..000000000 --- a/pkg/solana/client/multinode/send_only_node.go +++ /dev/null @@ -1,181 +0,0 @@ -package client - -import ( - "context" - "fmt" - "net/url" - "sync" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -type sendOnlyClient[ - CHAIN_ID ID, -] interface { - Close() - ChainID(context.Context) (CHAIN_ID, error) - Dial(ctx context.Context) error -} - -// SendOnlyNode represents one node used as a sendonly -type SendOnlyNode[ - CHAIN_ID ID, - RPC any, -] interface { - // Start may attempt to connect to the node, but should only return error for misconfiguration - never for temporary errors. - Start(context.Context) error - Close() error - - ConfiguredChainID() CHAIN_ID - RPC() RPC - - String() string - // State returns NodeState - State() NodeState - // Name is a unique identifier for this node. - Name() string -} - -// It only supports sending transactions -// It must use an http(s) url -type sendOnlyNode[ - CHAIN_ID ID, - RPC sendOnlyClient[CHAIN_ID], -] struct { - services.StateMachine - - stateMu sync.RWMutex // protects state* fields - state NodeState - - rpc RPC - uri url.URL - log logger.Logger - name string - chainID CHAIN_ID - chStop services.StopChan - wg sync.WaitGroup -} - -// NewSendOnlyNode returns a new sendonly node -func NewSendOnlyNode[ - CHAIN_ID ID, - RPC sendOnlyClient[CHAIN_ID], -]( - lggr logger.Logger, - httpuri url.URL, - name string, - chainID CHAIN_ID, - rpc RPC, -) SendOnlyNode[CHAIN_ID, RPC] { - s := new(sendOnlyNode[CHAIN_ID, RPC]) - s.name = name - s.log = logger.Named(logger.Named(lggr, "SendOnlyNode"), name) - s.log = logger.With(s.log, - "nodeTier", "sendonly", - ) - s.rpc = rpc - s.uri = httpuri - s.chainID = chainID - s.chStop = make(chan struct{}) - return s -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Start(ctx context.Context) error { - return s.StartOnce(s.name, func() error { - s.start(ctx) - return nil - }) -} - -// Start setups up and verifies the sendonly node -// Should only be called once in a node's lifecycle -func (s *sendOnlyNode[CHAIN_ID, RPC]) start(startCtx context.Context) { - if s.State() != NodeStateUndialed { - panic(fmt.Sprintf("cannot dial node with state %v", s.state)) - } - - err := s.rpc.Dial(startCtx) - if err != nil { - promPoolRPCNodeTransitionsToUnusable.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorw("Dial failed: SendOnly Node is unusable", "err", err) - s.setState(NodeStateUnusable) - return - } - s.setState(NodeStateDialed) - - if s.chainID.String() == "0" { - // Skip verification if chainID is zero - s.log.Warn("sendonly rpc ChainID verification skipped") - } else { - chainID, err := s.rpc.ChainID(startCtx) - if err != nil || chainID.String() != s.chainID.String() { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - if err != nil { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err) - s.setState(NodeStateUnreachable) - } else { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc() - s.log.Errorf( - "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s", - chainID.String(), - s.chainID.String(), - s.name, - ) - s.setState(NodeStateInvalidChainID) - } - // Since it has failed, spin up the verifyLoop that will keep - // retrying until success - s.wg.Add(1) - go s.verifyLoop() - return - } - } - - promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc() - s.setState(NodeStateAlive) - s.log.Infow("Sendonly RPC Node is online", "nodeState", s.state) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Close() error { - return s.StopOnce(s.name, func() error { - s.rpc.Close() - close(s.chStop) - s.wg.Wait() - s.setState(NodeStateClosed) - return nil - }) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) ConfiguredChainID() CHAIN_ID { - return s.chainID -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) RPC() RPC { - return s.rpc -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) String() string { - return fmt.Sprintf("(%s)%s:%s", Secondary.String(), s.name, s.uri.Redacted()) -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) setState(state NodeState) (changed bool) { - s.stateMu.Lock() - defer s.stateMu.Unlock() - if s.state == state { - return false - } - s.state = state - return true -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) State() NodeState { - s.stateMu.RLock() - defer s.stateMu.RUnlock() - return s.state -} - -func (s *sendOnlyNode[CHAIN_ID, RPC]) Name() string { - return s.name -} diff --git a/pkg/solana/client/multinode/send_only_node_lifecycle.go b/pkg/solana/client/multinode/send_only_node_lifecycle.go deleted file mode 100644 index 83642feba..000000000 --- a/pkg/solana/client/multinode/send_only_node_lifecycle.go +++ /dev/null @@ -1,65 +0,0 @@ -package client - -import ( - "fmt" - "time" -) - -// verifyLoop may only be triggered once, on Start, if initial chain ID check -// fails. -// -// It will continue checking until success and then exit permanently. -func (s *sendOnlyNode[CHAIN_ID, RPC]) verifyLoop() { - defer s.wg.Done() - ctx, cancel := s.chStop.NewCtx() - defer cancel() - - backoff := NewRedialBackoff() - for { - select { - case <-ctx.Done(): - return - case <-time.After(backoff.Duration()): - } - chainID, err := s.rpc.ChainID(ctx) - if err != nil { - ok := s.IfStarted(func() { - if changed := s.setState(NodeStateUnreachable); changed { - promPoolRPCNodeTransitionsToUnreachable.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Errorw(fmt.Sprintf("Verify failed: %v", err), "err", err) - continue - } else if chainID.String() != s.chainID.String() { - ok := s.IfStarted(func() { - if changed := s.setState(NodeStateInvalidChainID); changed { - promPoolRPCNodeTransitionsToInvalidChainID.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Errorf( - "sendonly rpc ChainID doesn't match local chain ID: RPC ID=%s, local ID=%s, node name=%s", - chainID.String(), - s.chainID.String(), - s.name, - ) - - continue - } - ok := s.IfStarted(func() { - if changed := s.setState(NodeStateAlive); changed { - promPoolRPCNodeTransitionsToAlive.WithLabelValues(s.chainID.String(), s.name).Inc() - } - }) - if !ok { - return - } - s.log.Infow("Sendonly RPC Node is online", "NodeState", s.state) - return - } -} diff --git a/pkg/solana/client/multinode/transaction_sender.go b/pkg/solana/client/multinode/transaction_sender.go deleted file mode 100644 index 06b2e18be..000000000 --- a/pkg/solana/client/multinode/transaction_sender.go +++ /dev/null @@ -1,281 +0,0 @@ -package client - -import ( - "context" - "errors" - "fmt" - "math" - "slices" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -var ( - // PromMultiNodeInvariantViolations reports violation of our assumptions - PromMultiNodeInvariantViolations = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "solana_multi_node_invariant_violations", - Help: "The number of invariant violations", - }, []string{"network", "chainId", "invariant"}) -) - -type SendTxResult interface { - Code() SendTxReturnCode - Error() error -} - -const sendTxQuorum = 0.7 - -// SendTxRPCClient - defines interface of an RPC used by TransactionSender to broadcast transaction -type SendTxRPCClient[TX any, RESULT SendTxResult] interface { - // SendTransaction errors returned should include name or other unique identifier of the RPC - SendTransaction(ctx context.Context, tx TX) RESULT -} - -func NewTransactionSender[TX any, RESULT SendTxResult, CHAIN_ID ID, RPC SendTxRPCClient[TX, RESULT]]( - lggr logger.Logger, - chainID CHAIN_ID, - chainFamily string, - multiNode *MultiNode[CHAIN_ID, RPC], - newResult func(err error) RESULT, - sendTxSoftTimeout time.Duration, -) *TransactionSender[TX, RESULT, CHAIN_ID, RPC] { - if sendTxSoftTimeout == 0 { - sendTxSoftTimeout = QueryTimeout / 2 - } - return &TransactionSender[TX, RESULT, CHAIN_ID, RPC]{ - chainID: chainID, - chainFamily: chainFamily, - lggr: logger.Sugared(lggr).Named("TransactionSender").With("chainID", chainID.String()), - multiNode: multiNode, - newResult: newResult, - sendTxSoftTimeout: sendTxSoftTimeout, - chStop: make(services.StopChan), - } -} - -type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID ID, RPC SendTxRPCClient[TX, RESULT]] struct { - services.StateMachine - chainID CHAIN_ID - chainFamily string - lggr logger.SugaredLogger - multiNode *MultiNode[CHAIN_ID, RPC] - newResult func(err error) RESULT - sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation - - wg sync.WaitGroup // waits for all reporting goroutines to finish - chStop services.StopChan -} - -// SendTransaction - broadcasts transaction to all the send-only and primary nodes in MultiNode. -// A returned nil or error does not guarantee that the transaction will or won't be included. Additional checks must be -// performed to determine the final state. -// -// Send-only nodes' results are ignored as they tend to return false-positive responses. Broadcast to them is necessary -// to speed up the propagation of TX in the network. -// -// Handling of primary nodes' results consists of collection and aggregation. -// In the collection step, we gather as many results as possible while minimizing waiting time. This operation succeeds -// on one of the following conditions: -// * Received at least one success -// * Received at least one result and `sendTxSoftTimeout` expired -// * Received results from the sufficient number of nodes defined by sendTxQuorum. -// The aggregation is based on the following conditions: -// * If there is at least one success - returns success -// * If there is at least one terminal error - returns terminal error -// * If there is both success and terminal error - returns success and reports invariant violation -// * Otherwise, returns any (effectively random) of the errors. -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) RESULT { - var result RESULT - if !txSender.IfStarted(func() { - txResults := make(chan RESULT) - txResultsToReport := make(chan RESULT) - primaryNodeWg := sync.WaitGroup{} - - healthyNodesNum := 0 - err := txSender.multiNode.DoAll(ctx, func(ctx context.Context, rpc RPC, isSendOnly bool) { - if isSendOnly { - txSender.wg.Add(1) - go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - defer txSender.wg.Done() - // Send-only nodes' results are ignored as they tend to return false-positive responses. - // Broadcast to them is necessary to speed up the propagation of TX in the network. - _ = txSender.broadcastTxAsync(ctx, rpc, tx) - }(ctx) - return - } - - // Primary Nodes - healthyNodesNum++ - primaryNodeWg.Add(1) - go func(ctx context.Context) { - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - defer primaryNodeWg.Done() - r := txSender.broadcastTxAsync(ctx, rpc, tx) - select { - case <-ctx.Done(): - return - case txResults <- r: - } - - select { - case <-ctx.Done(): - return - case txResultsToReport <- r: - } - }(ctx) - }) - - // This needs to be done in parallel so the reporting knows when it's done (when the channel is closed) - txSender.wg.Add(1) - go func() { - defer txSender.wg.Done() - primaryNodeWg.Wait() - close(txResultsToReport) - close(txResults) - }() - - if err != nil { - result = txSender.newResult(err) - return - } - - txSender.wg.Add(1) - go txSender.reportSendTxAnomalies(ctx, tx, txResultsToReport) - - result = txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) - }) { - result = txSender.newResult(errors.New("TransactionSender not started")) - } - - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) RESULT { - result := rpc.SendTransaction(ctx, tx) - txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", result.Error()) - if !slices.Contains(sendTxSuccessfulCodes, result.Code()) && ctx.Err() == nil { - txSender.lggr.Warnw("RPC returned error", "tx", tx, "err", result.Error()) - } - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(ctx context.Context, tx TX, txResults <-chan RESULT) { - defer txSender.wg.Done() - resultsByCode := sendTxResults[RESULT]{} - // txResults eventually will be closed - for txResult := range txResults { - resultsByCode[txResult.Code()] = append(resultsByCode[txResult.Code()], txResult) - } - - _, criticalErr := aggregateTxResults[RESULT](resultsByCode) - if criticalErr != nil && ctx.Err() == nil { - txSender.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) - PromMultiNodeInvariantViolations.WithLabelValues(txSender.chainFamily, txSender.chainID.String(), criticalErr.Error()).Inc() - } -} - -type sendTxResults[RESULT any] map[SendTxReturnCode][]RESULT - -func aggregateTxResults[RESULT any](resultsByCode sendTxResults[RESULT]) (result RESULT, criticalErr error) { - severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) - successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) - if hasSuccess { - // We assume that primary node would never report false positive txResult for a transaction. - // Thus, if such case occurs it's probably due to misconfiguration or a bug and requires manual intervention. - if hasSevereErrors { - const errMsg = "found contradictions in nodes replies on SendTransaction: got success and severe error" - // return success, since at least 1 node has accepted our broadcasted Tx, and thus it can now be included onchain - return successResults[0], errors.New(errMsg) - } - - // other errors are temporary - we are safe to return success - return successResults[0], nil - } - - if hasSevereErrors { - return severeErrors[0], nil - } - - // return temporary error - for _, r := range resultsByCode { - return r[0], nil - } - - criticalErr = fmt.Errorf("expected at least one response on SendTransaction") - return result, criticalErr -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan RESULT) RESULT { - if healthyNodesNum == 0 { - return txSender.newResult(ErroringNodeError) - } - requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := sendTxResults[RESULT]{} - var softTimeoutChan <-chan time.Time - var resultsCount int -loop: - for { - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to collect of the results before context was done", "tx", tx, "errorsByCode", errorsByCode) - return txSender.newResult(ctx.Err()) - case r := <-txResults: - errorsByCode[r.Code()] = append(errorsByCode[r.Code()], r) - resultsCount++ - if slices.Contains(sendTxSuccessfulCodes, r.Code()) || resultsCount >= requiredResults { - break loop - } - case <-softTimeoutChan: - txSender.lggr.Debugw("Send Tx soft timeout expired - returning responses we've collected so far", "tx", tx, "resultsCount", resultsCount, "requiredResults", requiredResults) - break loop - } - - if softTimeoutChan == nil { - tm := time.NewTimer(txSender.sendTxSoftTimeout) - softTimeoutChan = tm.C - // we are fine with stopping timer at the end of function - //nolint - defer tm.Stop() - } - } - - // ignore critical error as it's reported in reportSendTxAnomalies - result, _ := aggregateTxResults(errorsByCode) - txSender.lggr.Debugw("Collected results", "errorsByCode", errorsByCode, "result", result) - return result -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Start(ctx context.Context) error { - return txSender.StartOnce("TransactionSender", func() error { - return nil - }) -} - -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Close() error { - return txSender.StopOnce("TransactionSender", func() error { - txSender.lggr.Debug("Closing TransactionSender") - close(txSender.chStop) - txSender.wg.Wait() - return nil - }) -} - -// findFirstIn - returns the first existing key and value for the slice of keys -func findFirstIn[K comparable, V any](set map[K]V, keys []K) (V, bool) { - for _, k := range keys { - if v, ok := set[k]; ok { - return v, true - } - } - var zeroV V - return zeroV, false -} diff --git a/pkg/solana/client/multinode/types.go b/pkg/solana/client/multinode/types.go deleted file mode 100644 index 51b70e573..000000000 --- a/pkg/solana/client/multinode/types.go +++ /dev/null @@ -1,108 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math/big" -) - -// ID represents the base type, for any chain's ID. -// It should be convertible to a string, that can uniquely identify this chain -type ID fmt.Stringer - -// StringID enables using string directly as a ChainID -type StringID string - -func (s StringID) String() string { - return string(s) -} - -// Subscription represents an event subscription where events are -// delivered on a data channel. -// This is a generic interface for Subscription to represent used by clients. -type Subscription interface { - // Unsubscribe cancels the sending of events to the data channel - // and closes the error channel. Unsubscribe should be callable multiple - // times without causing an error. - Unsubscribe() - // Err returns the subscription error channel. The error channel receives - // a value if there is an issue with the subscription (e.g. the network connection - // delivering the events has been closed). Only one value will ever be sent. - // The error channel is closed by Unsubscribe. - Err() <-chan error -} - -// RPCClient includes all the necessary generalized RPC methods used by Node to perform health checks -type RPCClient[ - CHAIN_ID ID, - HEAD Head, -] interface { - // ChainID - fetches ChainID from the RPC to verify that it matches config - ChainID(ctx context.Context) (CHAIN_ID, error) - // Dial - prepares the RPC for usage. Can be called on fresh or closed RPC - Dial(ctx context.Context) error - // SubscribeToHeads - returns channel and subscription for new heads. - SubscribeToHeads(ctx context.Context) (<-chan HEAD, Subscription, error) - // SubscribeToFinalizedHeads - returns channel and subscription for finalized heads. - SubscribeToFinalizedHeads(ctx context.Context) (<-chan HEAD, Subscription, error) - // Ping - returns error if RPC is not reachable - Ping(context.Context) error - // IsSyncing - returns true if the RPC is in Syncing state and can not process calls - IsSyncing(ctx context.Context) (bool, error) - // UnsubscribeAllExcept - close all subscriptions except `subs` - UnsubscribeAllExcept(subs ...Subscription) - // Close - closes all subscriptions and aborts all RPC calls - Close() - // GetInterceptedChainInfo - returns latest and highest observed by application layer ChainInfo. - // latest ChainInfo is the most recent value received within a NodeClient's current lifecycle between Dial and DisconnectAll. - // highestUserObservations ChainInfo is the highest ChainInfo observed excluding health checks calls. - // Its values must not be reset. - // The results of corresponding calls, to get the most recent head and the latest finalized head, must be - // intercepted and reflected in ChainInfo before being returned to a caller. Otherwise, MultiNode is not able to - // provide repeatable read guarantee. - // DisconnectAll must reset latest ChainInfo to default value. - // Ensure implementation does not have a race condition when values are reset before request completion and as - // a result latest ChainInfo contains information from the previous cycle. - GetInterceptedChainInfo() (latest, highestUserObservations ChainInfo) -} - -// Head is the interface required by the NodeClient -type Head interface { - BlockNumber() int64 - BlockDifficulty() *big.Int - IsValid() bool -} - -// PoolChainInfoProvider - provides aggregation of nodes pool ChainInfo -type PoolChainInfoProvider interface { - // LatestChainInfo - returns number of live nodes available in the pool, so we can prevent the last alive node in a pool from being - // moved to out-of-sync state. It is better to have one out-of-sync node than no nodes at all. - // Returns highest latest ChainInfo within the alive nodes. E.g. most recent block number and highest block number - // observed by Node A are 10 and 15; Node B - 12 and 14. This method will return 12. - LatestChainInfo() (int, ChainInfo) - // HighestUserObservations - returns highest ChainInfo ever observed by any user of MultiNode. - HighestUserObservations() ChainInfo -} - -// ChainInfo - defines RPC's or MultiNode's view on the chain -type ChainInfo struct { - BlockNumber int64 - FinalizedBlockNumber int64 - TotalDifficulty *big.Int -} - -func MaxTotalDifficulty(a, b *big.Int) *big.Int { - if a == nil { - if b == nil { - return nil - } - - return big.NewInt(0).Set(b) - } - - if b == nil || a.Cmp(b) >= 0 { - return big.NewInt(0).Set(a) - } - - return big.NewInt(0).Set(b) -} diff --git a/pkg/solana/client/multinode_client.go b/pkg/solana/client/multinode_client.go index e6a70de9c..b97525044 100644 --- a/pkg/solana/client/multinode_client.go +++ b/pkg/solana/client/multinode_client.go @@ -12,8 +12,8 @@ import ( "github.com/gagliardetto/solana-go/rpc" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + mn "github.com/smartcontractkit/chainlink-framework/multinode" - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" ) @@ -102,8 +102,7 @@ func (m *MultiNodeClient) SubscribeToHeads(ctx context.Context) (<-chan *Head, m ctx, cancel, chStopInFlight, _ := m.acquireQueryCtx(ctx, m.cfg.TxTimeout()) defer cancel() - // TODO: BCFR-1070 - Add BlockPollInterval - pollInterval := m.cfg.MultiNode.FinalizedBlockPollInterval() // Use same interval as finalized polling + pollInterval := m.cfg.MultiNode.NewHeadsPollInterval() if pollInterval == 0 { return nil, nil, errors.New("PollInterval is 0") } diff --git a/pkg/solana/config/multinode.go b/pkg/solana/config/multinode.go deleted file mode 100644 index d002d489e..000000000 --- a/pkg/solana/config/multinode.go +++ /dev/null @@ -1,206 +0,0 @@ -package config - -import ( - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode" -) - -// MultiNodeConfig is a wrapper to provide required functions while keeping configs Public -type MultiNodeConfig struct { - MultiNode -} - -type MultiNode struct { - // Feature flag - Enabled *bool - - // Node Configs - PollFailureThreshold *uint32 - PollInterval *config.Duration - SelectionMode *string - SyncThreshold *uint32 - NodeIsSyncingEnabled *bool - LeaseDuration *config.Duration - FinalizedBlockPollInterval *config.Duration - EnforceRepeatableRead *bool - DeathDeclarationDelay *config.Duration - - // Chain Configs - NodeNoNewHeadsThreshold *config.Duration - NoNewFinalizedHeadsThreshold *config.Duration - FinalityDepth *uint32 - FinalityTagEnabled *bool - FinalizedBlockOffset *uint32 -} - -func (c *MultiNodeConfig) Enabled() bool { - return c.MultiNode.Enabled != nil && *c.MultiNode.Enabled -} - -func (c *MultiNodeConfig) PollFailureThreshold() uint32 { - return *c.MultiNode.PollFailureThreshold -} - -func (c *MultiNodeConfig) PollInterval() time.Duration { - return c.MultiNode.PollInterval.Duration() -} - -func (c *MultiNodeConfig) SelectionMode() string { - return *c.MultiNode.SelectionMode -} - -func (c *MultiNodeConfig) SyncThreshold() uint32 { - return *c.MultiNode.SyncThreshold -} - -func (c *MultiNodeConfig) NodeIsSyncingEnabled() bool { - return *c.MultiNode.NodeIsSyncingEnabled -} - -func (c *MultiNodeConfig) LeaseDuration() time.Duration { return c.MultiNode.LeaseDuration.Duration() } - -func (c *MultiNodeConfig) FinalizedBlockPollInterval() time.Duration { - return c.MultiNode.FinalizedBlockPollInterval.Duration() -} - -func (c *MultiNodeConfig) EnforceRepeatableRead() bool { return *c.MultiNode.EnforceRepeatableRead } - -func (c *MultiNodeConfig) DeathDeclarationDelay() time.Duration { - return c.MultiNode.DeathDeclarationDelay.Duration() -} - -func (c *MultiNodeConfig) NodeNoNewHeadsThreshold() time.Duration { - return c.MultiNode.NodeNoNewHeadsThreshold.Duration() -} - -func (c *MultiNodeConfig) NoNewFinalizedHeadsThreshold() time.Duration { - return c.MultiNode.NoNewFinalizedHeadsThreshold.Duration() -} - -func (c *MultiNodeConfig) FinalityDepth() uint32 { return *c.MultiNode.FinalityDepth } - -func (c *MultiNodeConfig) FinalityTagEnabled() bool { return *c.MultiNode.FinalityTagEnabled } - -func (c *MultiNodeConfig) FinalizedBlockOffset() uint32 { return *c.MultiNode.FinalizedBlockOffset } - -func (c *MultiNodeConfig) SetDefaults() { - // MultiNode is disabled as it's not fully implemented yet: BCFR-122 - if c.MultiNode.Enabled == nil { - c.MultiNode.Enabled = ptr(false) - } - - /* Node Configs */ - // Failure threshold for polling set to 5 to tolerate some polling failures before taking action. - if c.MultiNode.PollFailureThreshold == nil { - c.MultiNode.PollFailureThreshold = ptr(uint32(5)) - } - // Poll interval is set to 15 seconds to ensure timely updates while minimizing resource usage. - if c.MultiNode.PollInterval == nil { - c.MultiNode.PollInterval = config.MustNewDuration(15 * time.Second) - } - // Selection mode defaults to priority level to enable using node priorities - if c.MultiNode.SelectionMode == nil { - c.MultiNode.SelectionMode = ptr(mn.NodeSelectionModePriorityLevel) - } - // The sync threshold is set to 10 to allow for some flexibility in node synchronization before considering it out of sync. - if c.MultiNode.SyncThreshold == nil { - c.MultiNode.SyncThreshold = ptr(uint32(10)) - } - // Lease duration is set to 1 minute by default to allow node locks for a reasonable amount of time. - if c.MultiNode.LeaseDuration == nil { - c.MultiNode.LeaseDuration = config.MustNewDuration(time.Minute) - } - // Node syncing is not relevant for Solana and is disabled by default. - if c.MultiNode.NodeIsSyncingEnabled == nil { - c.MultiNode.NodeIsSyncingEnabled = ptr(false) - } - // The finalized block polling interval is set to 5 seconds to ensure timely updates while minimizing resource usage. - if c.MultiNode.FinalizedBlockPollInterval == nil { - c.MultiNode.FinalizedBlockPollInterval = config.MustNewDuration(5 * time.Second) - } - // Repeatable read guarantee should be enforced by default. - if c.MultiNode.EnforceRepeatableRead == nil { - c.MultiNode.EnforceRepeatableRead = ptr(true) - } - // The delay before declaring a node dead is set to 20 seconds to give nodes time to recover from temporary issues. - if c.MultiNode.DeathDeclarationDelay == nil { - c.MultiNode.DeathDeclarationDelay = config.MustNewDuration(20 * time.Second) - } - - /* Chain Configs */ - // Threshold for no new heads is set to 20 seconds, assuming that heads should update at a reasonable pace. - if c.MultiNode.NodeNoNewHeadsThreshold == nil { - c.MultiNode.NodeNoNewHeadsThreshold = config.MustNewDuration(20 * time.Second) - } - // Similar to heads, finalized heads should be updated within 20 seconds. - if c.MultiNode.NoNewFinalizedHeadsThreshold == nil { - c.MultiNode.NoNewFinalizedHeadsThreshold = config.MustNewDuration(20 * time.Second) - } - // Finality tags are used in Solana and enabled by default. - if c.MultiNode.FinalityTagEnabled == nil { - c.MultiNode.FinalityTagEnabled = ptr(true) - } - // Finality depth will not be used since finality tags are enabled. - if c.MultiNode.FinalityDepth == nil { - c.MultiNode.FinalityDepth = ptr(uint32(0)) - } - // Finalized block offset allows for RPCs to be slightly behind the finalized block. - if c.MultiNode.FinalizedBlockOffset == nil { - c.MultiNode.FinalizedBlockOffset = ptr(uint32(50)) - } -} - -func (c *MultiNodeConfig) SetFrom(f *MultiNodeConfig) { - if f.MultiNode.Enabled != nil { - c.MultiNode.Enabled = f.MultiNode.Enabled - } - - // Node Configs - if f.MultiNode.PollFailureThreshold != nil { - c.MultiNode.PollFailureThreshold = f.MultiNode.PollFailureThreshold - } - if f.MultiNode.PollInterval != nil { - c.MultiNode.PollInterval = f.MultiNode.PollInterval - } - if f.MultiNode.SelectionMode != nil { - c.MultiNode.SelectionMode = f.MultiNode.SelectionMode - } - if f.MultiNode.SyncThreshold != nil { - c.MultiNode.SyncThreshold = f.MultiNode.SyncThreshold - } - if f.MultiNode.NodeIsSyncingEnabled != nil { - c.MultiNode.NodeIsSyncingEnabled = f.MultiNode.NodeIsSyncingEnabled - } - if f.MultiNode.LeaseDuration != nil { - c.MultiNode.LeaseDuration = f.MultiNode.LeaseDuration - } - if f.MultiNode.FinalizedBlockPollInterval != nil { - c.MultiNode.FinalizedBlockPollInterval = f.MultiNode.FinalizedBlockPollInterval - } - if f.MultiNode.EnforceRepeatableRead != nil { - c.MultiNode.EnforceRepeatableRead = f.MultiNode.EnforceRepeatableRead - } - if f.MultiNode.DeathDeclarationDelay != nil { - c.MultiNode.DeathDeclarationDelay = f.MultiNode.DeathDeclarationDelay - } - - // Chain Configs - if f.MultiNode.NodeNoNewHeadsThreshold != nil { - c.MultiNode.NodeNoNewHeadsThreshold = f.MultiNode.NodeNoNewHeadsThreshold - } - if f.MultiNode.NoNewFinalizedHeadsThreshold != nil { - c.MultiNode.NoNewFinalizedHeadsThreshold = f.MultiNode.NoNewFinalizedHeadsThreshold - } - if f.MultiNode.FinalityDepth != nil { - c.MultiNode.FinalityDepth = f.MultiNode.FinalityDepth - } - if f.MultiNode.FinalityTagEnabled != nil { - c.MultiNode.FinalityTagEnabled = f.MultiNode.FinalityTagEnabled - } - if f.MultiNode.FinalizedBlockOffset != nil { - c.MultiNode.FinalizedBlockOffset = f.MultiNode.FinalizedBlockOffset - } -} diff --git a/pkg/solana/config/toml.go b/pkg/solana/config/toml.go index 9d46c0b65..5a1d64a10 100644 --- a/pkg/solana/config/toml.go +++ b/pkg/solana/config/toml.go @@ -12,6 +12,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" relaytypes "github.com/smartcontractkit/chainlink-common/pkg/types" + mn "github.com/smartcontractkit/chainlink-framework/multinode" + mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" ) type TOMLConfigs []*TOMLConfig @@ -113,7 +115,7 @@ type TOMLConfig struct { // Do not access directly, use [IsEnabled] Enabled *bool Chain - MultiNode MultiNodeConfig + MultiNode mnCfg.MultiNodeConfig Nodes Nodes } @@ -312,12 +314,57 @@ func (c *TOMLConfig) ListNodes() Nodes { func (c *TOMLConfig) SetDefaults() { c.Chain.SetDefaults() - c.MultiNode.SetDefaults() + c.MultiNode.SetFrom(defaultMultiNodeConfig) } func NewDefault() *TOMLConfig { cfg := &TOMLConfig{} cfg.Chain.SetDefaults() - cfg.MultiNode.SetDefaults() + cfg.MultiNode.SetFrom(defaultMultiNodeConfig) + return cfg +} + +var defaultMultiNodeConfig = &mnCfg.MultiNodeConfig{ + MultiNode: mnCfg.MultiNode{ + // Have multinode disabled by default + Enabled: ptr(false), + /* Node Configs */ + // Failure threshold for polling set to 5 to tolerate some polling failures before taking action. + PollFailureThreshold: ptr(uint32(5)), + // Poll interval is set to 15 seconds to ensure timely updates while minimizing resource usage. + PollInterval: config.MustNewDuration(15 * time.Second), + // Selection mode defaults to priority level to enable using node priorities + SelectionMode: ptr(mn.NodeSelectionModePriorityLevel), + // The sync threshold is set to 10 to allow for some flexibility in node synchronization before considering it out of sync. + SyncThreshold: ptr(uint32(10)), + // Lease duration is set to 1 minute by default to allow node locks for a reasonable amount of time. + LeaseDuration: config.MustNewDuration(time.Minute), + // Node syncing is not relevant for Solana and is disabled by default. + NodeIsSyncingEnabled: ptr(false), + // The new heads polling interval is set to 5 seconds to ensure timely updates while minimizing resource usage. + NewHeadsPollInterval: config.MustNewDuration(5 * time.Second), + // The finalized block polling interval is set to 5 seconds to ensure timely updates while minimizing resource usage. + FinalizedBlockPollInterval: config.MustNewDuration(5 * time.Second), + // Repeatable read guarantee should be enforced by default. + EnforceRepeatableRead: ptr(true), + // The delay before declaring a node dead is set to 20 seconds to give nodes time to recover from temporary issues. + DeathDeclarationDelay: config.MustNewDuration(20 * time.Second), + /* Chain Configs */ + // Threshold for no new heads is set to 20 seconds, assuming that heads should update at a reasonable pace. + NodeNoNewHeadsThreshold: config.MustNewDuration(20 * time.Second), + // Similar to heads, finalized heads should be updated within 20 seconds. + NoNewFinalizedHeadsThreshold: config.MustNewDuration(20 * time.Second), + // Finality tags are used in Solana and enabled by default. + FinalityTagEnabled: ptr(true), + // Finality depth will not be used since finality tags are enabled. + FinalityDepth: ptr(uint32(0)), + // Finalized block offset allows for RPCs to be slightly behind the finalized block. + FinalizedBlockOffset: ptr(uint32(50)), + }, +} + +func NewDefaultMultiNodeConfig() mnCfg.MultiNodeConfig { + cfg := mnCfg.MultiNodeConfig{} + cfg.SetFrom(defaultMultiNodeConfig) return cfg }