From c5537496da8b96ba8b4382ff594c445d9deb2a2c Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 15 Sep 2025 12:28:36 +0200 Subject: [PATCH 01/19] tools: use new golang 1.24 tool directive --- tools/Dockerfile | 3 +-- tools/go.mod | 17 ++++++++++------- tools/go.sum | 11 ++++------- tools/tools.go | 14 -------------- 4 files changed, 15 insertions(+), 30 deletions(-) delete mode 100644 tools/tools.go diff --git a/tools/Dockerfile b/tools/Dockerfile index 1b5a3972ff2..7937662de1c 100644 --- a/tools/Dockerfile +++ b/tools/Dockerfile @@ -10,8 +10,7 @@ RUN cd /tmp \ && mkdir -p /tmp/build/.cache \ && mkdir -p /tmp/build/.modcache \ && cd /tmp/tools \ - && CGO_ENABLED=0 go install -trimpath github.com/golangci/golangci-lint/cmd/golangci-lint \ - && CGO_ENABLED=0 golangci-lint custom \ + && CGO_ENABLED=0 go tool github.com/golangci/golangci-lint/cmd/golangci-lint custom \ && mv ./custom-gcl /usr/local/bin/custom-gcl \ && chmod -R 777 /tmp/build/ \ && git config --global --add safe.directory /build diff --git a/tools/go.mod b/tools/go.mod index 0c0a993ab9e..696e6755d5c 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -2,12 +2,6 @@ module github.com/lightningnetwork/lnd/tools go 1.24.6 -require ( - github.com/btcsuite/btcd v0.24.2 - github.com/golangci/golangci-lint v1.64.5 - github.com/rinchsan/gosimports v0.1.5 -) - require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect @@ -36,6 +30,7 @@ require ( github.com/bombsimon/wsl/v4 v4.5.0 // indirect github.com/breml/bidichk v0.3.2 // indirect github.com/breml/errchkjson v0.4.0 // indirect + github.com/btcsuite/btcd v0.24.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect @@ -82,6 +77,7 @@ require ( github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-printf-func-name v0.1.0 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect + github.com/golangci/golangci-lint v1.64.5 // indirect github.com/golangci/misspell v0.6.0 // indirect github.com/golangci/plugin-module-register v0.1.1 // indirect github.com/golangci/revgrep v0.8.0 // indirect @@ -149,6 +145,7 @@ require ( github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raeperd/recvcheck v0.2.0 // indirect + github.com/rinchsan/gosimports v0.3.8 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/ryancurrah/gomodguard v1.3.5 // indirect @@ -196,7 +193,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.37.0 // indirect + golang.org/x/crypto v0.33.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect golang.org/x/mod v0.23.0 // indirect golang.org/x/sync v0.13.0 // indirect @@ -211,3 +208,9 @@ require ( mvdan.cc/gofumpt v0.7.0 // indirect mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect ) + +tool ( + github.com/btcsuite/btcd + github.com/golangci/golangci-lint/cmd/golangci-lint + github.com/rinchsan/gosimports +) diff --git a/tools/go.sum b/tools/go.sum index 3fec23ed8b2..f9175b21958 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -527,8 +527,8 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4l github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI= github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= -github.com/rinchsan/gosimports v0.1.5 h1:Z/l9lS79z0xgKC6fLJYmDdY44D0LFwo3MzaMtWvMKpY= -github.com/rinchsan/gosimports v0.1.5/go.mod h1:102/jU2cwf9fpa/YM9D9o4gSen2Vg8Jl80Sxctgd9N0= +github.com/rinchsan/gosimports v0.3.8 h1:X4Pb9yFf6teHvogorT04yK/0W2Df7eHO79biCcYrA4c= +github.com/rinchsan/gosimports v0.3.8/go.mod h1:t0567k69sUHjLvJMPDsV31THZC+8UIbY1oL7NW+0I2c= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -674,8 +674,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 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= @@ -714,7 +714,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -840,7 +839,6 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -928,7 +926,6 @@ golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0t golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= diff --git a/tools/tools.go b/tools/tools.go deleted file mode 100644 index dfa1260a543..00000000000 --- a/tools/tools.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build tools -// +build tools - -package lnd - -// The other imports represent our build tools. Instead of defining a commit we -// want to use for those golang based tools, we use the go mod versioning system -// to unify the way we manage dependencies. So we define our build tool -// dependencies here and pin the version in go.mod. -import ( - _ "github.com/btcsuite/btcd" - _ "github.com/golangci/golangci-lint/cmd/golangci-lint" - _ "github.com/rinchsan/gosimports/cmd/gosimports" -) From ed64aea0c046e4380eef9a52c8ca72d1b8ae932b Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 15 Sep 2025 14:47:57 +0200 Subject: [PATCH 02/19] tools: update golangci-lint to v2 The config file format changed. The tool golangci-lint migrate was used to migrate the old config. However old comments and also the structure of the disabled linters was preserved. Moreover the new v2 version introduced new linters, we disable 3 of them because they are very noise and we do not really want to check for them: funcorder, noinlineerr, embeddedstructfieldcheck. --- .golangci.yml | 381 ++++++++++++++++++++----------------- tools/.custom-gcl.yml | 13 +- tools/Dockerfile | 2 +- tools/go.mod | 190 ++++++++++--------- tools/go.sum | 432 ++++++++++++++++++++++-------------------- 5 files changed, 552 insertions(+), 466 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 73d7ad4b5ec..4a42e131772 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,9 @@ +version: "2" + run: # If you change this please also update GO_VERSION in Makefile (then run # `make lint` to see where else it needs to be updated as well). - go: "1.24.6" + go: 1.24.6 # Abort after 10 minutes. timeout: 10m @@ -21,95 +23,8 @@ run: - kvdb_sqlite - integration -linters-settings: - custom: - ll: - type: "module" - description: "Custom lll linter with 'S' log line exclusion." - settings: - # Max line length, lines longer will be reported. - line-length: 80 - # Tab width in spaces. - tab-width: 8 - # The regex that we will use to detect the start of an `S` log line. - log-regex: "^\\s*.*(L|l)og\\.(Info|Debug|Trace|Warn|Error|Critical)S\\(" - - errorlint: - # Check for incorrect fmt.Errorf error wrapping. - errorf: true - - gofmt: - # simplify code: gofmt with `-s` option, true by default - simplify: true - - tagliatelle: - case: - rules: - json: snake - - whitespace: - multi-func: true - multi-if: true - - gosec: - excludes: - - G402 # Look for bad TLS connection settings. - - G306 # Poor file permissions used when writing to a new file. - - G601 # Implicit memory aliasing in for loop. - - G115 # Integer overflow in conversion. - - staticcheck: - checks: ["-SA1019"] - - funlen: - # Checks the number of lines in a function. - # If lower than 0, disable the check. - lines: 200 - # Checks the number of statements in a function. - statements: 80 - - dupl: - # Tokens count to trigger issue. - threshold: 200 - - nestif: - # Minimal complexity of if statements to report. - min-complexity: 10 - - nlreturn: - # Size of the block (including return statement that is still "OK") - # so no return split required. - block-size: 3 - - gomnd: - # List of numbers to exclude from analysis. - # The numbers should be written as string. - # Values always ignored: "1", "1.0", "0" and "0.0" - # Default: [] - ignored-numbers: - - '0666' - - '0755' - - # List of function patterns to exclude from analysis. - # Values always ignored: `time.Date` - # Default: [] - ignored-functions: - - 'math.*' - - 'strconv.ParseInt' - - 'errors.Wrap' - - gomoddirectives: - replace-local: true - replace-allow-list: - # See go.mod for the explanation why these are needed. - - github.com/ulikunitz/xz - - github.com/gogo/protobuf - - google.golang.org/protobuf - - github.com/lightningnetwork/lnd/sqldb - - linters: - enable-all: true + default: all disable: # We instead use our own custom line length linter called `ll` since # then we can ignore log lines. @@ -142,14 +57,10 @@ linters: - unparam - wastedassign - # Disable gofumpt as it has weird behavior regarding formatting multiple - # lines for a function which is in conflict with our contribution - # guidelines. See https://github.com/mvdan/gofumpt/issues/235. - - gofumpt - - # Disable whitespace linter as it has conflict rules against our + # Disable whitespace linters as it has conflict rules against our # contribution guidelines. - wsl + - wsl_v5 # Allow using default empty values. - exhaustruct @@ -211,88 +122,210 @@ linters: - gosmopolitan - intrange - goconst + + # Disable function order linter because we structure exported and unexported + # functions differently. + - funcorder + + # Disable noinlineerr linter because we use it to inline errors. + - noinlineerr + + # Disable embeddedstructfieldcheck linter because we use it to align + # structs. Because sometimes we have atomic fields that need to be aligned + # with means we need to assure that the field is at the beginning of the + # struct. + - embeddedstructfieldcheck + - # Deprecated linters that have been replaced by newer ones. - - tenv + settings: + dupl: + # Tokens count to trigger issue. + threshold: 200 + errorlint: + # Check for incorrect fmt.Errorf error wrapping. + errorf: true + + funlen: + # Checks the number of lines in a function. + # If lower than 0, disable the check. + lines: 200 + # Checks the number of statements in a function. + statements: 80 + + gomoddirectives: + # See project's go.mod for the explanation why these are needed. + replace-allow-list: + - github.com/ulikunitz/xz + - github.com/gogo/protobuf + - google.golang.org/protobuf + - github.com/lightningnetwork/lnd/sqldb + replace-local: true + + gosec: + excludes: + - G402 # Look for bad TLS connection settings. + - G306 # Poor file permissions used when writing to a new file. + - G601 # Implicit memory aliasing in for loop. + - G115 # Integer overflow in conversion. + + nestif: + # Minimal complexity of if statements to report. + min-complexity: 10 + + nlreturn: + # Size of the block (including return statement that is still "OK") + # so no return split required. + block-size: 3 + + staticcheck: + checks: + - -SA1019 + + tagliatelle: + case: + rules: + json: snake + + whitespace: + multi-if: true + multi-func: true + + custom: + ll: + type: module + description: Custom lll linter with 'S' log line exclusion. + settings: + # Max line length, lines longer will be reported. + line-length: 80 + # The regex that we will use to detect the start of an `S` log line. + log-regex: ^\s*.*(L|l)og\.(Info|Debug|Trace|Warn|Error|Critical)S\( + # Tab width in spaces. + tab-width: 8 + + exclusions: + # Mode of the generated files analysis. + # + # - `strict`: sources are excluded by strictly following the Go generated file convention. + # Source files that have lines matching only the following regular expression will be excluded: `^// Code generated .* DO NOT EDIT\.$` + # This line must appear before the first non-comment, non-blank text in the file. + # https://go.dev/s/generatedcode + # - `lax`: sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`, etc. + # - `disable`: disable the generated files exclusion. + # + # Default: strict + generated: lax + + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + + rules: + - linters: + # Allow duplications in tests so it's easier to follow a single unit + - dupl + - funlen + - gosec + - revive + # Exclude gosec from running for tests so that tests with weak + # randomness (math/rand) will pass the linter. + path: _test\.go + + - linters: + # forcetypeassert is skipped for the mock because the test would fail + # if the returned value doesn't match the type, so there's no need to + # check the convert. + - forcetypeassert + - revive + path: mock* + + - linters: + - funlen + - gosec + path: test* + + # Allow duplicated code and fmt.Printf() in DB migrations. + - linters: + - dupl + - forbidigo + - godot + path: channeldb/migration* + + # Allow duplicated code and fmt.Printf() in DB migration tests. + - linters: + - dupl + - forbidigo + - godot + path: channeldb/migtest + + # Allow fmt.Printf() in commands. + - linters: + - forbidigo + path: cmd/commands/* + + # Allow fmt.Printf() in config parsing. + - linters: + - forbidigo + path: config\.go + - linters: + - forbidigo + path: lnd\.go + + - linters: + # forcetypeassert is skipped for the mock because the test would fail + # if the returned value doesn't match the type, so there's no need to + # check the convert. + - forcetypeassert + path: lnmock/* + + - linters: + # forcetypeassert is skipped for the mock because the test would fail + # if the returned value doesn't match the type, so there's no need to + # check the convert. + - forcetypeassert + path: mock* + + # Skip autogenerated files for mobile and gRPC as well as copied code for + # internal use. + paths: + - third_party$ + - builtin$ + - examples$ + - "mobile\\/.*generated\\.go" + - "\\.pb\\.go$" + - "\\.pb\\.gw\\.go$" + - "internal\\/musig2v040" + - channeldb/migration_01_to_11 + - channeldb/migration/lnwire21 + issues: # Only show newly introduced problems. new-from-rev: 03eab4db64540aa5f789c617793e4459f4ba9e78 - # Skip autogenerated files for mobile and gRPC as well as copied code for - # internal use. - skip-files: - - "mobile\\/.*generated\\.go" - - "\\.pb\\.go$" - - "\\.pb\\.gw\\.go$" - - "internal\\/musig2v040" - - skip-dirs: - - channeldb/migration_01_to_11 - - channeldb/migration/lnwire21 - - exclude-rules: - # Exclude gosec from running for tests so that tests with weak randomness - # (math/rand) will pass the linter. - - path: _test\.go - linters: - - gosec - - funlen - - revive - # Allow duplications in tests so it's easier to follow a single unit - # test. - - dupl - - - path: mock* - linters: - - revive - # forcetypeassert is skipped for the mock because the test would fail - # if the returned value doesn't match the type, so there's no need to - # check the convert. - - forcetypeassert - - - path: test* - linters: - - gosec - - funlen - - # Allow duplicated code and fmt.Printf() in DB migrations. - - path: channeldb/migration* - linters: - - dupl - - forbidigo - - godot - - # Allow duplicated code and fmt.Printf() in DB migration tests. - - path: channeldb/migtest - linters: - - dupl - - forbidigo - - godot - - # Allow fmt.Printf() in commands. - - path: cmd/commands/* - linters: - - forbidigo - - # Allow fmt.Printf() in config parsing. - - path: config\.go - linters: - - forbidigo - - path: lnd\.go - linters: - - forbidigo - - - path: lnmock/* - linters: - # forcetypeassert is skipped for the mock because the test would fail - # if the returned value doesn't match the type, so there's no need to - # check the convert. - - forcetypeassert - - - path: mock* - linters: - # forcetypeassert is skipped for the mock because the test would fail - # if the returned value doesn't match the type, so there's no need to - # check the convert. - - forcetypeassert +formatters: + enable: + - gci + - gofmt + - goimports + + settings: + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true + + exclusions: + generated: lax + # Skip autogenerated files for mobile and gRPC as well as copied code for + # internal use. + paths: + - third_party$ + - builtin$ + - examples$ + - "mobile\\/.*generated\\.go" + - "\\.pb\\.go$" + - "\\.pb\\.gw\\.go$" + - "internal\\/musig2v040" + - channeldb/migration_01_to_11 + - channeldb/migration/lnwire21 \ No newline at end of file diff --git a/tools/.custom-gcl.yml b/tools/.custom-gcl.yml index 35895387a60..f628e0d1503 100644 --- a/tools/.custom-gcl.yml +++ b/tools/.custom-gcl.yml @@ -1,4 +1,15 @@ -version: v1.64.5 +# We are using a custom linter which is built cloning the version of +# golangci-lint from source below(thats what `golangci-lint custom` does +# internally) and adding the custom linters defined in this file. This means +# that this is the defining version for the linter as a whole when it comes to +# linter rules for example. +# The version pinned in the tools `go.mod` file is just the version we use to +# build the custom linter which is different and does not affect the linter +# rules itself. Hence both versions should always be updated together. +# +# NOTE: We cannot use untagged versions here. Always update the linter in the +# tools `go.mod` file and here as well. +version: v2.4.0 plugins: - module: 'github.com/lightningnetwork/lnd/tools/linters' path: ./linters \ No newline at end of file diff --git a/tools/Dockerfile b/tools/Dockerfile index 7937662de1c..e6fdd73be44 100644 --- a/tools/Dockerfile +++ b/tools/Dockerfile @@ -10,7 +10,7 @@ RUN cd /tmp \ && mkdir -p /tmp/build/.cache \ && mkdir -p /tmp/build/.modcache \ && cd /tmp/tools \ - && CGO_ENABLED=0 go tool github.com/golangci/golangci-lint/cmd/golangci-lint custom \ + && CGO_ENABLED=0 go tool github.com/golangci/golangci-lint/v2/cmd/golangci-lint custom \ && mv ./custom-gcl /usr/local/bin/custom-gcl \ && chmod -R 777 /tmp/build/ \ && git config --global --add safe.directory /build diff --git a/tools/go.mod b/tools/go.mod index 696e6755d5c..4651ef02a01 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -3,33 +3,39 @@ module github.com/lightningnetwork/lnd/tools go 1.24.6 require ( - 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect + 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - github.com/4meepo/tagalign v1.4.1 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.0.0 // indirect - github.com/Antonboom/nilnil v1.0.1 // indirect - github.com/Antonboom/testifylint v1.5.2 // indirect - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect - github.com/Crocmagnon/fatcontext v0.7.1 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.6 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.0 // indirect + github.com/Antonboom/nilnil v1.1.0 // indirect + github.com/Antonboom/testifylint v1.6.1 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect - github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect + github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect github.com/aead/siphash v1.0.1 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect - github.com/alexkohler/nakedret/v2 v2.0.5 // indirect + github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/alingse/nilnesserr v0.1.2 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/alingse/nilnesserr v0.2.0 // indirect + github.com/ashanbrown/forbidigo/v2 v2.1.0 // indirect + github.com/ashanbrown/makezero/v2 v2.0.1 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v4 v4.5.0 // indirect - github.com/breml/bidichk v0.3.2 // indirect - github.com/breml/errchkjson v0.4.0 // indirect + github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/bombsimon/wsl/v5 v5.1.1 // indirect + github.com/breml/bidichk v0.3.3 // indirect + github.com/breml/errchkjson v0.4.1 // indirect github.com/btcsuite/btcd v0.24.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect @@ -38,29 +44,35 @@ require ( github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/btcsuite/winsvc v1.0.0 // indirect - github.com/butuzov/ireturn v0.3.1 // indirect + github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.8.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/catenacyber/perfsprint v0.9.1 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect - github.com/chavacava/garif v0.1.0 // indirect - github.com/ckaznocha/intrange v0.3.0 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.5 // indirect + github.com/daixiang0/gci v0.13.7 // indirect + github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/lru v1.0.0 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect github.com/ettle/strcase v0.2.0 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.5 // indirect + github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.9 // indirect - github.com/go-critic/go-critic v0.12.0 // indirect + github.com/ghostiam/protogetter v0.3.15 // indirect + github.com/go-critic/go-critic v0.13.0 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -68,24 +80,27 @@ require ( github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect + github.com/golangci/asciicheck v0.5.0 // indirect + github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.0 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golangci-lint v1.64.5 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/golangci-lint/v2 v2.4.1-0.20250818164121-838684c5bc0c // indirect + github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect + github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect + github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect github.com/gostaticanalysis/nilerr v0.1.1 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect @@ -95,26 +110,29 @@ require ( github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jessevdk/go-flags v1.4.0 // indirect - github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/jrick/logrotate v1.0.0 // indirect github.com/julz/importas v0.2.0 // indirect github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect - github.com/kisielk/errcheck v1.8.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.5 // indirect + github.com/kisielk/errcheck v1.9.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.6 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/kunwardeep/paralleltest v1.0.14 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.1 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect + github.com/ldez/exptostd v0.4.4 // indirect + github.com/ldez/gomoddirectives v0.7.0 // indirect + github.com/ldez/grignotin v0.10.0 // indirect github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect - github.com/macabu/inamedparam v0.1.3 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/macabu/inamedparam v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect @@ -122,24 +140,24 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.6.1 // indirect + github.com/mgechev/revive v1.11.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/nunnatsa/ginkgolinter v0.20.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.7.1 // indirect + github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect + github.com/quasilyte/go-ruleguard v0.4.4 // indirect github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect @@ -147,24 +165,23 @@ require ( github.com/raeperd/recvcheck v0.2.0 // indirect github.com/rinchsan/gosimports v0.3.8 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect - github.com/ryancurrah/gomodguard v1.3.5 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.1 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.8 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/tenv v1.12.1 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.7 // indirect github.com/spf13/viper v1.12.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect @@ -172,45 +189,48 @@ require ( github.com/stretchr/testify v1.10.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tdakkota/asciicheck v0.4.0 // indirect - github.com/tetafro/godot v1.4.20 // indirect - github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect - github.com/timonwong/loggercheck v0.10.1 // indirect - github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/tetafro/godot v1.5.1 // indirect + github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect + github.com/timonwong/loggercheck v0.11.0 // indirect + github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect - github.com/xen0n/gosmopolitan v1.2.2 // indirect + github.com/uudashr/iface v1.4.1 // indirect + github.com/xen0n/gosmopolitan v1.3.0 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.0 // indirect - go-simpler.org/sloglint v0.9.0 // indirect - go.uber.org/atomic v1.7.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.2.0 // indirect + go.augendre.info/fatcontext v0.8.1 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.33.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.23.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - golang.org/x/tools v0.30.0 // indirect - google.golang.org/protobuf v1.36.4 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20250620022241-b7579e27df2b // indirect + golang.org/x/mod v0.27.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.36.0 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.6.0 // indirect - mvdan.cc/gofumpt v0.7.0 // indirect - mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect + honnef.co/go/tools v0.6.1 // indirect + mvdan.cc/gofumpt v0.8.0 // indirect + mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect ) tool ( github.com/btcsuite/btcd - github.com/golangci/golangci-lint/cmd/golangci-lint + // Once golangci-lint v2.4.1 update it here. + // Also don't forget to update the .custom-gcl.yml file. + github.com/golangci/golangci-lint/v2/cmd/golangci-lint github.com/rinchsan/gosimports ) diff --git a/tools/go.sum b/tools/go.sum index f9175b21958..e9898b85d51 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,5 +1,5 @@ -4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= -4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gocheckcompilerdirectives v1.3.0 h1:Ew5y5CtcAAQeTVKUVFrE7EwHMrTO6BggtEj8BZSjZ3A= +4d63.com/gocheckcompilerdirectives v1.3.0/go.mod h1:ofsJ4zx2QAuIP/NO/NAh1ig6R1Fb18/GI7RVMwz7kAY= 4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -34,58 +34,66 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.4.1 h1:GYTu2FaPGOGb/xJalcqHeD4il5BiCywyEYZOA55P6J4= -github.com/4meepo/tagalign v1.4.1/go.mod h1:2H9Yu6sZ67hmuraFgfZkNcg5Py9Ch/Om9l2K/2W1qS4= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= -github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= -github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= -github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= -github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= -github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= +github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= +github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= +github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= +github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= +github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= +github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= -github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= +github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 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= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= +github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= +github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/ashanbrown/forbidigo/v2 v2.1.0 h1:NAxZrWqNUQiDz19FKScQ/xvwzmij6BiOw3S0+QUQ+Hs= +github.com/ashanbrown/forbidigo/v2 v2.1.0/go.mod h1:0zZfdNAuZIL7rSComLGthgc/9/n2FqspBOH90xlCHdA= +github.com/ashanbrown/makezero/v2 v2.0.1 h1:r8GtKetWOgoJ4sLyUx97UTwyt2dO7WkGFHizn/Lo8TY= +github.com/ashanbrown/makezero/v2 v2.0.1/go.mod h1:kKU4IMxmYW1M4fiEHMb2vc5SFoPzXvgbMR9gIp5pjSw= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -94,12 +102,14 @@ github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5 github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= -github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= -github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= -github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= -github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= -github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= +github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= +github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v5 v5.1.1 h1:cQg5KJf9FlctAH4cpL9vLKnziYknoCMCdqXl0wjl72Q= +github.com/bombsimon/wsl/v5 v5.1.1/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= +github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= +github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= +github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= +github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= @@ -129,14 +139,14 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E= +github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.8.1 h1:bGOHuzHe0IkoGeY831RW4aSlt1lPRd3WRAScSWOaV7E= -github.com/catenacyber/perfsprint v0.8.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= +github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -144,20 +154,32 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= -github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +github.com/ckaznocha/intrange v0.3.1 h1:j1onQyXvHUsPWujDH6WIjhyH26gkRt/txNlV7LspvJs= +github.com/ckaznocha/intrange v0.3.1/go.mod h1:QVepyz1AkUoFQkpEqksSYpNpUo3c5W7nWh/s6SHIJJk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= -github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= +github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= +github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -170,8 +192,8 @@ github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8 github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -182,8 +204,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= +github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -192,10 +214,10 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= -github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= -github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= +github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= +github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= +github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -205,8 +227,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -231,8 +253,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -271,22 +293,28 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= +github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= +github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= +github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint v1.64.5 h1:5omC86XFBKXZgCrVdUWU+WNHKd+CWCxNx717KXnzKZY= -github.com/golangci/golangci-lint v1.64.5/go.mod h1:WZnwq8TF0z61h3jLQ7Sk5trcP7b3kUFxLD6l1ivtdvU= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/golangci-lint/v2 v2.4.1-0.20250818164121-838684c5bc0c h1:1RFhewLhOV3AWgBOlLhjozyh+Q+AcYBmb4UOst1m7DI= +github.com/golangci/golangci-lint/v2 v2.4.1-0.20250818164121-838684c5bc0c/go.mod h1:UrZZ+4nTVngTvsTHDgyQjTKhtTrvGlnVg9V0Q4vC1JM= +github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= +github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= +github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -299,10 +327,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -313,8 +340,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -324,8 +351,9 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= -github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= +github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= @@ -355,12 +383,12 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -376,11 +404,11 @@ github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= -github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= -github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= +github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= +github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= -github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= +github.com/kkHAIKE/contextcheck v1.1.6 h1:7HIyRcnyzxL9Lz06NGhiKvenXq7Zw6Q0UQu/ttjfJCE= +github.com/kkHAIKE/contextcheck v1.1.6/go.mod h1:3dDbMRNBFaq8HFXWC1JyvDSPm43CmE6IuHam8Wr0rkg= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -395,26 +423,32 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= +github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.1 h1:DIollgQ3LWZMp3HJbSXsdE2giJxMfjyHj3eX4oiD6JU= -github.com/ldez/exptostd v0.4.1/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= +github.com/ldez/exptostd v0.4.4 h1:58AtQjnLcT/tI5W/1KU7xE/O7zW9RAWB6c/ScQAnfus= +github.com/ldez/exptostd v0.4.4/go.mod h1:QfdzPw6oHjFVdNV7ILoPu5sw3OZ3OG1JS0I5JN3J4Js= +github.com/ldez/gomoddirectives v0.7.0 h1:EOx8Dd56BZYSez11LVgdj025lKwlP0/E5OLSl9HDwsY= +github.com/ldez/gomoddirectives v0.7.0/go.mod h1:wR4v8MN9J8kcwvrkzrx6sC9xe9Cp68gWYCsda5xvyGc= +github.com/ldez/grignotin v0.10.0 h1:NQPeh1E/Eza4F0exCeC1WkpnLvgUcQDT8MQ1vOLML0E= +github.com/ldez/grignotin v0.10.0/go.mod h1:oR4iCKUP9fwoeO6vCQeD7M5SMxCT6xdVas4vg0h1LaI= github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= -github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE= +github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= @@ -427,13 +461,12 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.6.1 h1:ncK0ZCMWtb8GXwVAmk+IeWF2ULIDsvRxSRfg5sTwQ2w= -github.com/mgechev/revive v1.6.1/go.mod h1:/2tfHWVO8UQi/hqJsIYNEKELi+DJy/e+PQpLgTB1v88= +github.com/mgechev/revive v1.11.0 h1:b/gLLpBE427o+Xmd8G58gSA+KtBwxWinH/A565Awh0w= +github.com/mgechev/revive v1.11.0/go.mod h1:tI0oLF/2uj+InHCBLrrqfTKfjtFTBCFFfG05auyzgdw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -445,6 +478,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= @@ -453,25 +488,23 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.0 h1:CnHRFAeBS3LdLI9h+Jidbcc5KH71GKOmaBZQk8Srnto= -github.com/nunnatsa/ginkgolinter v0.19.0/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= +github.com/nunnatsa/ginkgolinter v0.20.0 h1:OmWLkAFO2HUTYcU6mprnKud1Ey5pVdiVNYGO5HVicx8= +github.com/nunnatsa/ginkgolinter v0.20.0/go.mod h1:dCIuFlTPfQerXgGUju3VygfAFPdC5aE1mdacCDKDJcQ= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -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= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= +github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -481,16 +514,15 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= +github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= +github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -515,8 +547,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= +github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= +github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= @@ -533,23 +565,25 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= -github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= +github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb7Elr+g= +github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.1 h1:IcBt3TpI5Y9VN1YlwjSpM2cHu0i3Iw52QM+PQeg7jN8= -github.com/securego/gosec/v2 v2.22.1/go.mod h1:4bb95X4Jz7VSEPdVjC0hD7C/yR6kdeUBvCPOy9gDQ0g= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= +github.com/securego/gosec/v2 v2.22.8 h1:3NMpmfXO8wAVFZPNsd3EscOTa32Jyo6FLLlW53bexMI= +github.com/securego/gosec/v2 v2.22.8/go.mod h1:ZAw8K2ikuH9qDlfdV87JmNghnVfKB1XC7+TVzk6Utto= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -559,23 +593,22 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= -github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= +github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -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= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -584,38 +617,30 @@ github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8B github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tdakkota/asciicheck v0.4.0 h1:VZ13Itw4k1i7d+dpDSNS8Op645XgGHpkCEh/WHicgWw= -github.com/tdakkota/asciicheck v0.4.0/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.20 h1:z/p8Ek55UdNvzt4TFn2zx2KscpW4rWqcnUrdmvWJj7E= -github.com/tetafro/godot v1.4.20/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= -github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= +github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= +github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= +github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= +github.com/timonwong/loggercheck v0.11.0/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tomarrell/wrapcheck/v2 v2.11.0 h1:BJSt36snX9+4WTIXeJ7nvHBQBcm1h2SjQMSlmQ6aFSU= +github.com/tomarrell/wrapcheck/v2 v2.11.0/go.mod h1:wFL9pDWDAbXhhPZZt+nG8Fu+h29TtnZ2MW6Lx4BRXIU= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= @@ -624,10 +649,12 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= -github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= -github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= +github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= +github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= +github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= @@ -645,25 +672,27 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.2.0 h1:2NP/XudpPmfBhQKX4rMk+zDYIj//qbt4hfZmSSTcpj8= +go.augendre.info/arangolint v0.2.0/go.mod h1:Vx4KSJwu48tkE+8uxuf0cbBnAPgnt8O1KWiT7bljq7w= +go.augendre.info/fatcontext v0.8.1 h1:/T4+cCjpL9g71gJpcFAgVo/K5VFpqlN+NPU7QXxD5+A= +go.augendre.info/fatcontext v0.8.1/go.mod h1:r3Qz4ZOzex66wfyyj5VZ1xUcl81vzvHQ6/GWzzlMEwA= 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.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= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -674,8 +703,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -690,8 +719,8 @@ golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWB golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20250620022241-b7579e27df2b h1:KdrhdYPDUvJTvrDK9gdjfFd6JTk8vA1WJoldYSi0kHo= +golang.org/x/exp/typeparams v0.0.0-20250620022241-b7579e27df2b/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ= 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= @@ -716,13 +745,11 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= @@ -761,14 +788,12 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 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.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -790,8 +815,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -844,19 +869,16 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 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.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -867,13 +889,11 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -928,13 +948,15 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= 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.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1014,8 +1036,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1045,12 +1067,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.6.0 h1:TAODvD3knlq75WCp2nyGJtT4LeRV/o7NN9nYPeVJXf8= -honnef.co/go/tools v0.6.0/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= +honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= +honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= +mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= +mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= +mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= +mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 0a7cc026bb40a58f08e8b5eba89657312d9632df Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 15 Sep 2025 14:50:06 +0200 Subject: [PATCH 03/19] linter: remove unsupported linters from the codebase --- channeldb/migration_01_to_11/migration_11_invoices_test.go | 2 +- invoices/invoiceregistry.go | 2 +- itest/lnd_route_blinding_test.go | 2 -- lnwire/typed_fee.go | 2 +- watchtower/wtdb/client_db.go | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/channeldb/migration_01_to_11/migration_11_invoices_test.go b/channeldb/migration_01_to_11/migration_11_invoices_test.go index 55c188bd953..4098fe5a6cc 100644 --- a/channeldb/migration_01_to_11/migration_11_invoices_test.go +++ b/channeldb/migration_01_to_11/migration_11_invoices_test.go @@ -41,7 +41,7 @@ func beforeMigrationFuncV11(t *testing.T, d *DB, invoices []Invoice) { invoiceNum++ var buf bytes.Buffer - err := serializeInvoiceLegacy(&buf, &invoice) // nolint:scopelint + err := serializeInvoiceLegacy(&buf, &invoice) if err != nil { return err } diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index 8815bb37405..6528c4b1cac 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -1581,7 +1581,7 @@ func (i *InvoiceRegistry) notifyClients(hash lntypes.Hash, // invoiceSubscriptionKit defines that are common to both all invoice // subscribers and single invoice subscribers. type invoiceSubscriptionKit struct { - id uint32 // nolint:structcheck + id uint32 // quit is a chan mouted to InvoiceRegistry that signals a shutdown. quit chan struct{} diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index af2612d244f..b6c7f102c6d 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -423,8 +423,6 @@ func (b *blindedForwardTest) cleanup() { // createRouteToBlinded queries for a route from alice to the blinded path // provided. -// -//nolint:gomnd func (b *blindedForwardTest) createRouteToBlinded(paymentAmt int64, blindedPath *lnrpc.BlindedPaymentPath) *lnrpc.Route { diff --git a/lnwire/typed_fee.go b/lnwire/typed_fee.go index 6b139f196f7..2a5c6b385e3 100644 --- a/lnwire/typed_fee.go +++ b/lnwire/typed_fee.go @@ -20,7 +20,7 @@ type Fee struct { // type from a given TLV stream. func (l *Fee) Record() tlv.Record { return tlv.MakeStaticRecord( - FeeRecordType, l, 8, feeEncoder, feeDecoder, //nolint:gomnd + FeeRecordType, l, 8, feeEncoder, feeDecoder, ) } diff --git a/watchtower/wtdb/client_db.go b/watchtower/wtdb/client_db.go index 6e6adacc023..9fa03a3c17a 100644 --- a/watchtower/wtdb/client_db.go +++ b/watchtower/wtdb/client_db.go @@ -2964,7 +2964,7 @@ func getRealChannelID(chanIDIndexBkt kvdb.RBucket, } chanIDBytes := chanIDIndexBkt.Get(dbIDBytes) - if len(chanIDBytes) != 32 { //nolint:gomnd + if len(chanIDBytes) != 32 { return nil, fmt.Errorf("channel ID not found") } From 055da5f610245786d2136f78ca5e894a1704979e Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 15 Sep 2025 21:47:40 +0200 Subject: [PATCH 04/19] CI: also use go tool for gosimports --- Makefile | 13 ++++++------- tools/go.mod | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 6a883aa92da..7de8a97a13e 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,19 @@ PKG := github.com/lightningnetwork/lnd MOBILE_PKG := $(PKG)/mobile TOOLS_DIR := tools +TOOLS_MOD := $(TOOLS_DIR)/go.mod GOCC ?= go PREFIX ?= /usr/local +GOTOOL := GOWORK=off $(GOCC) tool -modfile=$(TOOLS_MOD) + + BTCD_PKG := github.com/btcsuite/btcd GOIMPORTS_PKG := github.com/rinchsan/gosimports/cmd/gosimports GO_BIN := ${GOPATH}/bin BTCD_BIN := $(GO_BIN)/btcd -GOIMPORTS_BIN := $(GO_BIN)/gosimports GOMOBILE_BIN := $(GO_BIN)/gomobile MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build @@ -88,10 +91,6 @@ $(BTCD_BIN): @$(call print, "Installing btcd.") cd $(TOOLS_DIR); $(GOCC) install -trimpath $(BTCD_PKG) -$(GOIMPORTS_BIN): - @$(call print, "Installing goimports.") - cd $(TOOLS_DIR); $(GOCC) install -trimpath $(GOIMPORTS_PKG) - # ============ # INSTALLATION # ============ @@ -315,9 +314,9 @@ fuzz: # ========= #? fmt: Format source code and fix imports -fmt: $(GOIMPORTS_BIN) +fmt: @$(call print, "Fixing imports.") - gosimports -w $(GOFILES_NOVENDOR) + $(GOTOOL) $(GOIMPORTS_PKG) -w $(GOFILES_NOVENDOR) @$(call print, "Formatting source.") gofmt -l -w -s $(GOFILES_NOVENDOR) diff --git a/tools/go.mod b/tools/go.mod index 4651ef02a01..6145fe3bc00 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -232,5 +232,5 @@ tool ( // Once golangci-lint v2.4.1 update it here. // Also don't forget to update the .custom-gcl.yml file. github.com/golangci/golangci-lint/v2/cmd/golangci-lint - github.com/rinchsan/gosimports + github.com/rinchsan/gosimports/cmd/gosimports ) From a21f44102beca19b114575aa5c572e4a8fda5556 Mon Sep 17 00:00:00 2001 From: ziggie Date: Fri, 19 Sep 2025 13:52:02 +0200 Subject: [PATCH 05/19] CI: remove unnecessary custom-gcl.yml file The custom file is only needed in the tools directory. --- .custom-gcl.yml | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .custom-gcl.yml diff --git a/.custom-gcl.yml b/.custom-gcl.yml deleted file mode 100644 index 6ca10094a07..00000000000 --- a/.custom-gcl.yml +++ /dev/null @@ -1,4 +0,0 @@ -version: v1.57.0 -plugins: - - module: 'github.com/lightningnetwork/lnd/tools/linters' - path: ./tools/linters \ No newline at end of file From 8cbfca8db540c60946bc5f065ee2392461f61363 Mon Sep 17 00:00:00 2001 From: ziggie Date: Fri, 19 Sep 2025 13:53:13 +0200 Subject: [PATCH 06/19] makefile: add linter config check --- Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7de8a97a13e..03b8fd43816 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ GOTOOL := GOWORK=off $(GOCC) tool -modfile=$(TOOLS_MOD) BTCD_PKG := github.com/btcsuite/btcd GOIMPORTS_PKG := github.com/rinchsan/gosimports/cmd/gosimports +GOLINT_PKG := github.com/golangci/golangci-lint/v2/cmd/golangci-lint GO_BIN := ${GOPATH}/bin BTCD_BIN := $(GO_BIN)/btcd @@ -339,12 +340,19 @@ check-go-version-dockerfile: check-go-version: check-go-version-dockerfile check-go-version-yaml #? lint-source: Run static code analysis -lint-source: docker-tools +lint-source: docker-tools @$(call print, "Linting source.") $(DOCKER_TOOLS) custom-gcl run -v $(LINT_WORKERS) +#? lint-config-check: Verify that the lint config is up to date +# We use the official linter here not our custom one because for checking the +# config file it does not matter. +lint-config-check: + @$(call print, "Checking lint config is up to date.") + $(GOTOOL) $(GOLINT_PKG) config verify -v + #? lint: Run static code analysis -lint: check-go-version lint-source +lint: check-go-version lint-config-check lint-source #? protolint: Lint proto files using protolint protolint: From 211e6adee5c9648fa7223ccb69d4ae53574afcd7 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 15 Sep 2025 12:22:21 +0200 Subject: [PATCH 07/19] lnwire: add NodeAnnouncement interface And ensure that both versions 1 and 2 implement it. --- lnwire/interfaces.go | 16 ++++++++++++++++ lnwire/node_announcement.go | 26 ++++++++++++++++++++++++++ lnwire/node_announcement_2.go | 26 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/lnwire/interfaces.go b/lnwire/interfaces.go index 3a8b7cbdfc1..975cd6c4c04 100644 --- a/lnwire/interfaces.go +++ b/lnwire/interfaces.go @@ -91,6 +91,22 @@ type ChannelUpdate interface { Message } +// NodeAnnouncement is an interface that must be satisfied by any message used +// to announce the existence of a node. +type NodeAnnouncement interface { + // NodePub returns the identity public key of the node. + NodePub() [33]byte + + // NodeFeatures returns the set of features supported by the node. + NodeFeatures() *FeatureVector + + // TimestampDesc returns a human-readable description of the + // timestamp of the announcement. + TimestampDesc() string + + Message +} + // ForwardingPolicy defines the set of forwarding constraints advertised in a // ChannelUpdate message. type ForwardingPolicy struct { diff --git a/lnwire/node_announcement.go b/lnwire/node_announcement.go index 0a7c60542ce..384327f376a 100644 --- a/lnwire/node_announcement.go +++ b/lnwire/node_announcement.go @@ -104,6 +104,10 @@ type NodeAnnouncement1 struct { // lnwire.Message interface. var _ Message = (*NodeAnnouncement1)(nil) +// A compile time check to ensure NodeAnnouncement1 implements the +// lnwire.NodeAnnouncement interface. +var _ NodeAnnouncement = (*NodeAnnouncement1)(nil) + // A compile time check to ensure NodeAnnouncement1 implements the // lnwire.SizeableMessage interface. var _ SizeableMessage = (*NodeAnnouncement1)(nil) @@ -217,3 +221,25 @@ func (a *NodeAnnouncement1) DataToSign() ([]byte, error) { func (a *NodeAnnouncement1) SerializedSize() (uint32, error) { return MessageSerializedSize(a) } + +// NodePub returns the identity public key of the node. +// +// NOTE: part of the NodeAnnouncement interface. +func (a *NodeAnnouncement1) NodePub() [33]byte { + return a.NodeID +} + +// NodeFeatures returns the set of features supported by the node. +// +// NOTE: part of the NodeAnnouncement interface. +func (a *NodeAnnouncement1) NodeFeatures() *FeatureVector { + return NewFeatureVector(a.Features, Features) +} + +// TimestampDesc returns a human-readable description of the timestamp of the +// announcement. +// +// NOTE: part of the NodeAnnouncement interface. +func (a *NodeAnnouncement1) TimestampDesc() string { + return fmt.Sprintf("timestamp=%d", a.Timestamp) +} diff --git a/lnwire/node_announcement_2.go b/lnwire/node_announcement_2.go index 23fcc509f3e..0b7142db01c 100644 --- a/lnwire/node_announcement_2.go +++ b/lnwire/node_announcement_2.go @@ -199,10 +199,36 @@ func (n *NodeAnnouncement2) MsgType() MessageType { return MsgNodeAnnouncement2 } +// NodePub returns the identity public key of the node. +// +// NOTE: part of the NodeAnnouncement interface. +func (n *NodeAnnouncement2) NodePub() [33]byte { + return n.NodeID.Val +} + +// NodeFeatures returns the set of features supported by the node. +// +// NOTE: part of the NodeAnnouncement interface. +func (n *NodeAnnouncement2) NodeFeatures() *FeatureVector { + return NewFeatureVector(&n.Features.Val, Features) +} + +// TimestampDesc returns a human-readable description of the timestamp of the +// announcement. +// +// NOTE: part of the NodeAnnouncement interface. +func (n *NodeAnnouncement2) TimestampDesc() string { + return fmt.Sprintf("block_height=%d", n.BlockHeight.Val) +} + // A compile-time check to ensure NodeAnnouncement2 implements the Message // interface. var _ Message = (*NodeAnnouncement2)(nil) +// A compile time check to ensure NodeAnnouncement2 implements the +// lnwire.NodeAnnouncement interface. +var _ NodeAnnouncement = (*NodeAnnouncement2)(nil) + // A compile-time check to ensure NodeAnnouncement2 implements the // PureTLVMessage interface. var _ PureTLVMessage = (*NodeAnnouncement2)(nil) From 49b39f120642e372d53a0fa3774b7888100b6c26 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 15 Sep 2025 12:09:52 +0200 Subject: [PATCH 08/19] lnwire: define GossipVersion and GossipMessage Define a GossipVersion enum along with a GossipMessage interface to be satisfied by all gossip related messages. This will be useful later on when we want to make decisions based on the protocol version that a message is part of. --- lnwire/interfaces.go | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lnwire/interfaces.go b/lnwire/interfaces.go index 975cd6c4c04..64d87f7c1ca 100644 --- a/lnwire/interfaces.go +++ b/lnwire/interfaces.go @@ -1,6 +1,39 @@ package lnwire -import "github.com/btcsuite/btcd/chaincfg/chainhash" +import ( + "fmt" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +// GossipVersion is a version number that describes the version of the +// gossip protocol that a gossip message was gossiped on. +type GossipVersion uint8 + +const ( + // GossipVersion1 is the initial version of the gossip protocol as + // defined in BOLT 7. This version of the protocol can only gossip P2WSH + // channels and makes use of ECDSA signatures. + GossipVersion1 GossipVersion = 1 + + // GossipVersion2 is the newest version of the gossip protocol. This + // version adds support for P2TR channels and makes use of Schnorr + // signatures. The BOLT number is TBD. + GossipVersion2 GossipVersion = 2 +) + +// String returns a string representation of the protocol version. +func (v GossipVersion) String() string { + return fmt.Sprintf("V%d", v) +} + +// GossipMessage is an interface that must be satisfied by all messages that are +// part of the gossip protocol. +type GossipMessage interface { + // GossipVersion returns the version of the gossip protocol that a + // message is part of. + GossipVersion() GossipVersion +} // AnnounceSignatures is an interface that represents a message used to // exchange signatures of a ChannelAnnouncment message during the funding flow. From 349dedbdccc4dd20613add385f4e5372ef606526 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 15 Sep 2025 12:27:14 +0200 Subject: [PATCH 09/19] lnwire: let gossip messages implement GossipMessage --- lnwire/announcement_signatures.go | 7 +++++++ lnwire/announcement_signatures_2.go | 7 +++++++ lnwire/channel_announcement.go | 7 +++++++ lnwire/channel_announcement_2.go | 7 +++++++ lnwire/channel_update.go | 7 +++++++ lnwire/channel_update_2.go | 7 +++++++ lnwire/interfaces.go | 4 ++++ lnwire/node_announcement.go | 7 +++++++ lnwire/node_announcement_2.go | 7 +++++++ 9 files changed, 60 insertions(+) diff --git a/lnwire/announcement_signatures.go b/lnwire/announcement_signatures.go index cf8f68be5ef..29ada700822 100644 --- a/lnwire/announcement_signatures.go +++ b/lnwire/announcement_signatures.go @@ -121,3 +121,10 @@ func (a *AnnounceSignatures1) SCID() ShortChannelID { func (a *AnnounceSignatures1) ChanID() ChannelID { return a.ChannelID } + +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (a *AnnounceSignatures1) GossipVersion() GossipVersion { + return GossipVersion1 +} diff --git a/lnwire/announcement_signatures_2.go b/lnwire/announcement_signatures_2.go index 04e4c0a9f1a..a2806f1ee2c 100644 --- a/lnwire/announcement_signatures_2.go +++ b/lnwire/announcement_signatures_2.go @@ -102,6 +102,13 @@ func (a *AnnounceSignatures2) MsgType() MessageType { return MsgAnnounceSignatures2 } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (a *AnnounceSignatures2) GossipVersion() GossipVersion { + return GossipVersion2 +} + // SerializedSize returns the serialized size of the message in bytes. // // This is part of the lnwire.SizeableMessage interface. diff --git a/lnwire/channel_announcement.go b/lnwire/channel_announcement.go index 05161cca835..cab8407283a 100644 --- a/lnwire/channel_announcement.go +++ b/lnwire/channel_announcement.go @@ -232,6 +232,13 @@ func (a *ChannelAnnouncement1) SCID() ShortChannelID { return a.ShortChannelID } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (a *ChannelAnnouncement1) GossipVersion() GossipVersion { + return GossipVersion1 +} + // A compile-time check to ensure that ChannelAnnouncement1 implements the // ChannelAnnouncement interface. var _ ChannelAnnouncement = (*ChannelAnnouncement1)(nil) diff --git a/lnwire/channel_announcement_2.go b/lnwire/channel_announcement_2.go index a82624a514e..9227584b6f5 100644 --- a/lnwire/channel_announcement_2.go +++ b/lnwire/channel_announcement_2.go @@ -307,6 +307,13 @@ func (c *ChannelAnnouncement2) SCID() ShortChannelID { return c.ShortChannelID.Val } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (c *ChannelAnnouncement2) GossipVersion() GossipVersion { + return GossipVersion2 +} + // A compile-time check to ensure that ChannelAnnouncement2 implements the // ChannelAnnouncement interface. var _ ChannelAnnouncement = (*ChannelAnnouncement2)(nil) diff --git a/lnwire/channel_update.go b/lnwire/channel_update.go index 558d81a9e91..ee797e7b721 100644 --- a/lnwire/channel_update.go +++ b/lnwire/channel_update.go @@ -363,6 +363,13 @@ func (a *ChannelUpdate1) ForwardingPolicy() *ForwardingPolicy { } } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (a *ChannelUpdate1) GossipVersion() GossipVersion { + return GossipVersion1 +} + // CmpAge can be used to determine if the update is older or newer than the // passed update. It returns 1 if this update is newer, -1 if it is older, and // 0 if they are the same age. diff --git a/lnwire/channel_update_2.go b/lnwire/channel_update_2.go index 7fe7670ed89..8e82fe9d7c8 100644 --- a/lnwire/channel_update_2.go +++ b/lnwire/channel_update_2.go @@ -85,6 +85,13 @@ type ChannelUpdate2 struct { ExtraSignedFields } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (c *ChannelUpdate2) GossipVersion() GossipVersion { + return GossipVersion2 +} + // Encode serializes the target ChannelUpdate2 into the passed io.Writer // observing the protocol version specified. // diff --git a/lnwire/interfaces.go b/lnwire/interfaces.go index 64d87f7c1ca..115b07d7bf3 100644 --- a/lnwire/interfaces.go +++ b/lnwire/interfaces.go @@ -45,6 +45,7 @@ type AnnounceSignatures interface { ChanID() ChannelID Message + GossipMessage } // ChannelAnnouncement is an interface that must be satisfied by any message @@ -66,6 +67,7 @@ type ChannelAnnouncement interface { Node2KeyBytes() [33]byte Message + GossipMessage } // CompareResult represents the result after comparing two things. @@ -122,6 +124,7 @@ type ChannelUpdate interface { SetSCID(scid ShortChannelID) Message + GossipMessage } // NodeAnnouncement is an interface that must be satisfied by any message used @@ -138,6 +141,7 @@ type NodeAnnouncement interface { TimestampDesc() string Message + GossipMessage } // ForwardingPolicy defines the set of forwarding constraints advertised in a diff --git a/lnwire/node_announcement.go b/lnwire/node_announcement.go index 384327f376a..468ac794e70 100644 --- a/lnwire/node_announcement.go +++ b/lnwire/node_announcement.go @@ -243,3 +243,10 @@ func (a *NodeAnnouncement1) NodeFeatures() *FeatureVector { func (a *NodeAnnouncement1) TimestampDesc() string { return fmt.Sprintf("timestamp=%d", a.Timestamp) } + +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (a *NodeAnnouncement1) GossipVersion() GossipVersion { + return GossipVersion1 +} diff --git a/lnwire/node_announcement_2.go b/lnwire/node_announcement_2.go index 0b7142db01c..93a3792a2d8 100644 --- a/lnwire/node_announcement_2.go +++ b/lnwire/node_announcement_2.go @@ -221,6 +221,13 @@ func (n *NodeAnnouncement2) TimestampDesc() string { return fmt.Sprintf("block_height=%d", n.BlockHeight.Val) } +// GossipVersion returns the gossip version that this message is part of. +// +// NOTE: this is part of the GossipMessage interface. +func (n *NodeAnnouncement2) GossipVersion() GossipVersion { + return GossipVersion2 +} + // A compile-time check to ensure NodeAnnouncement2 implements the Message // interface. var _ Message = (*NodeAnnouncement2)(nil) From eab2614eb7a7e1bff9a9e46914306b69ad65139c Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 15 Sep 2025 12:31:40 +0200 Subject: [PATCH 10/19] graph/db: use lnwire.GossipVersion instead of ProtocolVersion --- graph/db/sql_migration.go | 16 ++--- graph/db/sql_store.go | 128 ++++++++++++++++++-------------------- 2 files changed, 70 insertions(+), 74 deletions(-) diff --git a/graph/db/sql_migration.go b/graph/db/sql_migration.go index 7cc4c414e5b..e737718006d 100644 --- a/graph/db/sql_migration.go +++ b/graph/db/sql_migration.go @@ -423,7 +423,7 @@ func migrateSourceNode(ctx context.Context, kvdb kvdb.Backend, id, err := sqlDB.GetNodeIDByPubKey( ctx, sqlc.GetNodeIDByPubKeyParams{ PubKey: pub[:], - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err != nil { @@ -441,7 +441,9 @@ func migrateSourceNode(ctx context.Context, kvdb kvdb.Backend, // from the SQL database and checking that the expected DB ID and // pub key are returned. We don't need to do a whole node comparison // here, as this was already done in the previous migration step. - srcNodes, err := sqlDB.GetSourceNodesByVersion(ctx, int16(ProtocolV1)) + srcNodes, err := sqlDB.GetSourceNodesByVersion( + ctx, int16(lnwire.GossipVersion1), + ) if err != nil { return fmt.Errorf("could not get source nodes from SQL "+ "store: %w", err) @@ -1251,7 +1253,7 @@ func migrateZombieIndex(ctx context.Context, cfg *sqldb.QueryConfig, // Batch fetch all zombie channels from the database. rows, err := sqlDB.GetZombieChannelsSCIDs( ctx, sqlc.GetZombieChannelsSCIDsParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scids: scids, }, ) @@ -1327,7 +1329,7 @@ func migrateZombieIndex(ctx context.Context, cfg *sqldb.QueryConfig, err = sqlDB.UpsertZombieChannel( ctx, sqlc.UpsertZombieChannelParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scid: chanIDB, NodeKey1: pubKey1[:], NodeKey2: pubKey2[:], @@ -1443,7 +1445,7 @@ func insertNodeSQLMig(ctx context.Context, db SQLQueries, node *models.Node) (int64, error) { params := sqlc.InsertNodeMigParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: node.PubKeyBytes[:], } @@ -1564,7 +1566,7 @@ func insertChannelMig(ctx context.Context, db SQLQueries, } createParams := sqlc.InsertChannelMigParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scid: channelIDToBytes(edge.ChannelID), NodeID1: node1DBID, NodeID2: node2DBID, @@ -1655,7 +1657,7 @@ func insertChanEdgePolicyMig(ctx context.Context, tx SQLQueries, }) id, err := tx.InsertEdgePolicyMig(ctx, sqlc.InsertEdgePolicyMigParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: dbChan.channelID, NodeID: nodeID, Timelock: int32(edge.TimeLockDelta), diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go index f13408765c5..3921d621f2b 100644 --- a/graph/db/sql_store.go +++ b/graph/db/sql_store.go @@ -32,20 +32,6 @@ import ( "github.com/lightningnetwork/lnd/tor" ) -// ProtocolVersion is an enum that defines the gossip protocol version of a -// message. -type ProtocolVersion uint8 - -const ( - // ProtocolV1 is the gossip protocol version defined in BOLT #7. - ProtocolV1 ProtocolVersion = 1 -) - -// String returns a string representation of the protocol version. -func (v ProtocolVersion) String() string { - return fmt.Sprintf("V%d", v) -} - // SQLQueries is a subset of the sqlc.Querier interface that can be used to // execute queries against the SQL graph tables. // @@ -191,7 +177,7 @@ type SQLStore struct { chanScheduler batch.Scheduler[SQLQueries] nodeScheduler batch.Scheduler[SQLQueries] - srcNodes map[ProtocolVersion]*srcNodeInfo + srcNodes map[lnwire.GossipVersion]*srcNodeInfo srcNodeMu sync.Mutex } @@ -229,7 +215,7 @@ func NewSQLStore(cfg *SQLStoreConfig, db BatchedSQLQueries, db: db, rejectCache: newRejectCache(opts.RejectCacheSize), chanCache: newChannelCache(opts.ChannelCacheSize), - srcNodes: make(map[ProtocolVersion]*srcNodeInfo), + srcNodes: make(map[lnwire.GossipVersion]*srcNodeInfo), } s.chanScheduler = batch.NewTimeScheduler( @@ -301,7 +287,7 @@ func (s *SQLStore) HasNode(ctx context.Context, err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { dbNode, err := db.GetNodeByPubKey( ctx, sqlc.GetNodeByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: pubKey[:], }, ) @@ -344,7 +330,7 @@ func (s *SQLStore) AddrsForNode(ctx context.Context, // does. dbID, err := db.GetNodeIDByPubKey( ctx, sqlc.GetNodeIDByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: nodePub.SerializeCompressed(), }, ) @@ -380,7 +366,7 @@ func (s *SQLStore) DeleteNode(ctx context.Context, err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error { res, err := db.DeleteNodeByPubKey( ctx, sqlc.DeleteNodeByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: pubKey[:], }, ) @@ -459,7 +445,7 @@ func (s *SQLStore) LookupAlias(ctx context.Context, err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { dbNode, err := db.GetNodeByPubKey( ctx, sqlc.GetNodeByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: pub.SerializeCompressed(), }, ) @@ -495,7 +481,9 @@ func (s *SQLStore) SourceNode(ctx context.Context) (*models.Node, var node *models.Node err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { - _, nodePub, err := s.getSourceNode(ctx, db, ProtocolV1) + _, nodePub, err := s.getSourceNode( + ctx, db, lnwire.GossipVersion1, + ) if err != nil { return fmt.Errorf("unable to fetch V1 source node: %w", err) @@ -529,7 +517,9 @@ func (s *SQLStore) SetSourceNode(ctx context.Context, // Make sure that if a source node for this version is already // set, then the ID is the same as the one we are about to set. - dbSourceNodeID, _, err := s.getSourceNode(ctx, db, ProtocolV1) + dbSourceNodeID, _, err := s.getSourceNode( + ctx, db, lnwire.GossipVersion1, + ) if err != nil && !errors.Is(err, ErrSourceNodeNotSet) { return fmt.Errorf("unable to fetch source node: %w", err) @@ -682,7 +672,7 @@ func (s *SQLStore) AddChannelEdge(ctx context.Context, _, err := tx.GetChannelBySCID( ctx, sqlc.GetChannelBySCIDParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err == nil { @@ -720,7 +710,7 @@ func (s *SQLStore) AddChannelEdge(ctx context.Context, func (s *SQLStore) HighestChanID(ctx context.Context) (uint64, error) { var highestChanID uint64 err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { - chanID, err := db.HighestSCID(ctx, int16(ProtocolV1)) + chanID, err := db.HighestSCID(ctx, int16(lnwire.GossipVersion1)) if errors.Is(err, sql.ErrNoRows) { return nil } else if err != nil { @@ -843,7 +833,9 @@ func (s *SQLStore) ForEachSourceNodeChannel(ctx context.Context, otherNode *models.Node) error, reset func()) error { return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { - nodeID, nodePub, err := s.getSourceNode(ctx, db, ProtocolV1) + nodeID, nodePub, err := s.getSourceNode( + ctx, db, lnwire.GossipVersion1, + ) if err != nil { return fmt.Errorf("unable to fetch source node: %w", err) @@ -901,7 +893,7 @@ func (s *SQLStore) ForEachNode(ctx context.Context, return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { return forEachNodePaginated( ctx, s.cfg.QueryCfg, db, - ProtocolV1, func(_ context.Context, _ int64, + lnwire.GossipVersion1, func(_ context.Context, _ int64, node *models.Node) error { return cb(node) @@ -970,7 +962,7 @@ func (s *SQLStore) ForEachNodeChannel(ctx context.Context, nodePub route.Vertex, return s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { dbNode, err := db.GetNodeByPubKey( ctx, sqlc.GetNodeByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: nodePub[:], }, ) @@ -1111,7 +1103,7 @@ func (s *SQLStore) ChanUpdatesInHorizon(startTime, endTime time.Time, func(db SQLQueries) error { //nolint:ll params := sqlc.GetChannelsByPolicyLastUpdateRangeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), StartTime: sqldb.SQLInt64( startTime.Unix(), ), @@ -1259,7 +1251,7 @@ func (s *SQLStore) ForEachNodeCached(ctx context.Context, withAddrs bool, return db.ListNodeIDsAndPubKeys( ctx, sqlc.ListNodeIDsAndPubKeysParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ID: lastID, Limit: limit, }, @@ -1297,7 +1289,7 @@ func (s *SQLStore) ForEachNodeCached(ctx context.Context, withAddrs bool, // page. allChannels, err := db.ListChannelsForNodeIDs( ctx, sqlc.ListChannelsForNodeIDsParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Node1Ids: nodeIDs, Node2Ids: nodeIDs, }, @@ -1512,7 +1504,7 @@ func (s *SQLStore) ForEachChannelCacheable(cb func(*models.CachedEdgeInfo, return db.ListChannelsWithPoliciesForCachePaginated( ctx, sqlc.ListChannelsWithPoliciesForCachePaginatedParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ID: lastID, Limit: limit, }, @@ -1610,7 +1602,7 @@ func (s *SQLStore) FilterChannelRange(startHeight, endHeight uint32, //nolint:ll node1Policy, err := db.GetChannelPolicyByChannelAndNode( ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: dbChan.ID, NodeID: dbChan.NodeID1, }, @@ -1627,7 +1619,7 @@ func (s *SQLStore) FilterChannelRange(startHeight, endHeight uint32, //nolint:ll node2Policy, err := db.GetChannelPolicyByChannelAndNode( ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: dbChan.ID, NodeID: dbChan.NodeID2, }, @@ -1688,7 +1680,7 @@ func (s *SQLStore) MarkEdgeZombie(chanID uint64, err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error { return db.UpsertZombieChannel( ctx, sqlc.UpsertZombieChannelParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scid: chanIDB, NodeKey1: pubKey1[:], NodeKey2: pubKey2[:], @@ -1722,7 +1714,7 @@ func (s *SQLStore) MarkEdgeLive(chanID uint64) error { res, err := db.DeleteZombieChannel( ctx, sqlc.DeleteZombieChannelParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err != nil { @@ -1774,7 +1766,7 @@ func (s *SQLStore) IsZombieEdge(chanID uint64) (bool, [33]byte, [33]byte, zombie, err := db.GetZombieChannel( ctx, sqlc.GetZombieChannelParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -1809,7 +1801,9 @@ func (s *SQLStore) NumZombies() (uint64, error) { numZombies uint64 ) err := s.db.ExecTx(ctx, sqldb.ReadTxOpt(), func(db SQLQueries) error { - count, err := db.CountZombieChannels(ctx, int16(ProtocolV1)) + count, err := db.CountZombieChannels( + ctx, int16(lnwire.GossipVersion1), + ) if err != nil { return fmt.Errorf("unable to count zombie channels: %w", err) @@ -1955,7 +1949,7 @@ func (s *SQLStore) FetchChannelEdgesByID(chanID uint64) ( row, err := db.GetChannelBySCIDWithPolicies( ctx, sqlc.GetChannelBySCIDWithPoliciesParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -1964,7 +1958,7 @@ func (s *SQLStore) FetchChannelEdgesByID(chanID uint64) ( zombie, err := db.GetZombieChannel( ctx, sqlc.GetZombieChannelParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -2051,7 +2045,7 @@ func (s *SQLStore) FetchChannelEdgesByOutpoint(op *wire.OutPoint) ( row, err := db.GetChannelByOutpointWithPolicies( ctx, sqlc.GetChannelByOutpointWithPoliciesParams{ Outpoint: op.String(), - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -2152,7 +2146,7 @@ func (s *SQLStore) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool, channel, err := db.GetChannelBySCID( ctx, sqlc.GetChannelBySCIDParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -2160,7 +2154,7 @@ func (s *SQLStore) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool, isZombie, err = db.IsZombieChannel( ctx, sqlc.IsZombieChannelParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err != nil { @@ -2177,7 +2171,7 @@ func (s *SQLStore) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool, policy1, err := db.GetChannelPolicyByChannelAndNode( ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: channel.ID, NodeID: channel.NodeID1, }, @@ -2191,7 +2185,7 @@ func (s *SQLStore) HasChannelEdge(chanID uint64) (time.Time, time.Time, bool, policy2, err := db.GetChannelPolicyByChannelAndNode( ctx, sqlc.GetChannelPolicyByChannelAndNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: channel.ID, NodeID: channel.NodeID2, }, @@ -2233,7 +2227,7 @@ func (s *SQLStore) ChannelID(chanPoint *wire.OutPoint) (uint64, error) { chanID, err := db.GetSCIDByOutpoint( ctx, sqlc.GetSCIDByOutpointParams{ Outpoint: chanPoint.String(), - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -2358,7 +2352,7 @@ func (s *SQLStore) forEachChanWithPoliciesInSCIDList(ctx context.Context, return db.GetChannelsBySCIDWithPolicies( ctx, sqlc.GetChannelsBySCIDWithPoliciesParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scids: scids, }, ) @@ -2428,7 +2422,7 @@ func (s *SQLStore) FilterKnownChanIDs(chansInfo []ChannelUpdateInfo) ([]uint64, isZombie, err := db.IsZombieChannel( ctx, sqlc.IsZombieChannelParams{ Scid: channelIDToBytes(channelID), - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err != nil { @@ -2475,7 +2469,7 @@ func (s *SQLStore) forEachChanInSCIDList(ctx context.Context, db SQLQueries, return db.GetChannelsBySCIDs( ctx, sqlc.GetChannelsBySCIDsParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scids: scids, }, ) @@ -2721,7 +2715,7 @@ func (s *SQLStore) ChannelView() ([]EdgePoint, error) { return db.ListChannelsPaginated( ctx, sqlc.ListChannelsPaginatedParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ID: lastID, Limit: limit, }, @@ -3061,7 +3055,7 @@ func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries, dbID, err := db.GetNodeIDByPubKey( ctx, sqlc.GetNodeIDByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: nodePub[:], }, ) @@ -3073,7 +3067,7 @@ func forEachNodeDirectedChannel(ctx context.Context, db SQLQueries, rows, err := db.ListChannelsByNodeID( ctx, sqlc.ListChannelsByNodeIDParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), NodeID1: dbID, }, ) @@ -3189,7 +3183,7 @@ func forEachNodeCacheable(ctx context.Context, cfg *sqldb.QueryConfig, return db.ListNodeIDsAndPubKeys( ctx, sqlc.ListNodeIDsAndPubKeysParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ID: lastID, Limit: limit, }, @@ -3228,7 +3222,7 @@ func forEachNodeChannel(ctx context.Context, db SQLQueries, // Get all the V1 channels for this node. rows, err := db.ListChannelsByNodeID( ctx, sqlc.ListChannelsByNodeIDParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), NodeID1: id, }, ) @@ -3330,7 +3324,7 @@ func updateChanEdgePolicy(ctx context.Context, tx SQLQueries, dbChan, err := tx.GetChannelAndNodesBySCID( ctx, sqlc.GetChannelAndNodesBySCIDParams{ Scid: chanIDB, - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if errors.Is(err, sql.ErrNoRows) { @@ -3360,7 +3354,7 @@ func updateChanEdgePolicy(ctx context.Context, tx SQLQueries, }) id, err := tx.UpsertEdgePolicy(ctx, sqlc.UpsertEdgePolicyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ChannelID: dbChan.ID, NodeID: nodeID, Timelock: int32(edge.TimeLockDelta), @@ -3411,7 +3405,7 @@ func getNodeByPubKey(ctx context.Context, cfg *sqldb.QueryConfig, db SQLQueries, dbNode, err := db.GetNodeByPubKey( ctx, sqlc.GetNodeByPubKeyParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: pubKey[:], }, ) @@ -3464,7 +3458,7 @@ func buildNode(ctx context.Context, cfg *sqldb.QueryConfig, db SQLQueries, func buildNodeWithBatchData(dbNode sqlc.GraphNode, batchData *batchNodeData) (*models.Node, error) { - if dbNode.Version != int16(ProtocolV1) { + if dbNode.Version != int16(lnwire.GossipVersion1) { return nil, fmt.Errorf("unsupported node version: %d", dbNode.Version) } @@ -3591,7 +3585,7 @@ func upsertNode(ctx context.Context, db SQLQueries, node *models.Node) (int64, error) { params := sqlc.UpsertNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: node.PubKeyBytes[:], } @@ -3710,7 +3704,7 @@ func fetchNodeFeatures(ctx context.Context, queries SQLQueries, rows, err := queries.GetNodeFeaturesByPubKey( ctx, sqlc.GetNodeFeaturesByPubKeyParams{ PubKey: nodePub[:], - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) if err != nil { @@ -3945,7 +3939,7 @@ type srcNodeInfo struct { // sourceNode returns the DB node ID and pub key of the source node for the // specified protocol version. func (s *SQLStore) getSourceNode(ctx context.Context, db SQLQueries, - version ProtocolVersion) (int64, route.Vertex, error) { + version lnwire.GossipVersion) (int64, route.Vertex, error) { s.srcNodeMu.Lock() defer s.srcNodeMu.Unlock() @@ -4032,7 +4026,7 @@ func insertChannel(ctx context.Context, db SQLQueries, } createParams := sqlc.CreateChannelParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scid: channelIDToBytes(edge.ChannelID), NodeID1: node1DBID, NodeID2: node2DBID, @@ -4106,7 +4100,7 @@ func maybeCreateShellNode(ctx context.Context, db SQLQueries, dbNode, err := db.GetNodeByPubKey( ctx, sqlc.GetNodeByPubKeyParams{ PubKey: pubKey[:], - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), }, ) // The node exists. Return the ID. @@ -4119,7 +4113,7 @@ func maybeCreateShellNode(ctx context.Context, db SQLQueries, // Otherwise, the node does not exist, so we create a shell entry for // it. id, err := db.UpsertNode(ctx, sqlc.UpsertNodeParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), PubKey: pubKey[:], }) if err != nil { @@ -4187,7 +4181,7 @@ func buildEdgeInfoWithBatchData(chain chainhash.Hash, dbChan sqlc.GraphChannel, node1, node2 route.Vertex, batchData *batchChannelData) (*models.ChannelEdgeInfo, error) { - if dbChan.Version != int16(ProtocolV1) { + if dbChan.Version != int16(lnwire.GossipVersion1) { return nil, fmt.Errorf("unsupported channel version: %d", dbChan.Version) } @@ -5268,7 +5262,7 @@ func batchLoadChannelPolicyExtrasHelper(ctx context.Context, // graph. It uses the provided SQLQueries interface to fetch nodes in batches // and applies the provided processNode function to each node. func forEachNodePaginated(ctx context.Context, cfg *sqldb.QueryConfig, - db SQLQueries, protocol ProtocolVersion, + db SQLQueries, protocol lnwire.GossipVersion, processNode func(context.Context, int64, *models.Node) error) error { @@ -5334,7 +5328,7 @@ func forEachChannelWithPolicies(ctx context.Context, db SQLQueries, return db.ListChannelsWithPoliciesPaginated( ctx, sqlc.ListChannelsWithPoliciesPaginatedParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), ID: lastID, Limit: limit, }, @@ -5707,7 +5701,7 @@ func handleZombieMarking(ctx context.Context, db SQLQueries, return db.UpsertZombieChannel( ctx, sqlc.UpsertZombieChannelParams{ - Version: int16(ProtocolV1), + Version: int16(lnwire.GossipVersion1), Scid: channelIDToBytes(scid), NodeKey1: nodeKey1[:], NodeKey2: nodeKey2[:], From 6dbefd9e06d38e3d552f84fee09de238d2a55cd9 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 15 Sep 2025 12:40:59 +0200 Subject: [PATCH 11/19] discovery: let reject cache use gossip version in key Since the gossip protocols are completely disjoint, we need to treat messages on the two protocols completely separately and should not let rejections on one protocol affect how we treat messages on the other. --- discovery/gossiper.go | 41 ++++++++++++++++++++++++++++++-------- discovery/gossiper_test.go | 1 + 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 50dd3a57a2c..96a8c047ae3 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -437,15 +437,19 @@ func (c *cachedNetworkMsg) Size() (uint64, error) { // rejectCacheKey is the cache key that we'll use to track announcements we've // recently rejected. type rejectCacheKey struct { - pubkey [33]byte - chanID uint64 + gossipVersion lnwire.GossipVersion + pubkey [33]byte + chanID uint64 } // newRejectCacheKey returns a new cache key for the reject cache. -func newRejectCacheKey(cid uint64, pub [33]byte) rejectCacheKey { +func newRejectCacheKey(v lnwire.GossipVersion, cid uint64, + pub [33]byte) rejectCacheKey { + k := rejectCacheKey{ - chanID: cid, - pubkey: pub, + gossipVersion: v, + chanID: cid, + pubkey: pub, } return k @@ -1688,8 +1692,15 @@ func (d *AuthenticatedGossiper) PruneSyncState(peer route.Vertex) { func (d *AuthenticatedGossiper) isRecentlyRejectedMsg(msg lnwire.Message, peerPub [33]byte) bool { + // We only cache rejections for gossip messages. So if it is not + // a gossip message, we return false. + gMsg, ok := msg.(lnwire.GossipMessage) + if !ok { + return false + } + var scid uint64 - switch m := msg.(type) { + switch m := gMsg.(type) { case *lnwire.ChannelUpdate1: scid = m.ShortChannelID.ToUint64() @@ -1700,8 +1711,11 @@ func (d *AuthenticatedGossiper) isRecentlyRejectedMsg(msg lnwire.Message, return false } - _, err := d.recentRejects.Get(newRejectCacheKey(scid, peerPub)) - return err != cache.ErrElementNotFound + _, err := d.recentRejects.Get(newRejectCacheKey( + gMsg.GossipVersion(), scid, peerPub, + )) + + return !errors.Is(err, cache.ErrElementNotFound) } // retransmitStaleAnns examines all outgoing channels that the source node is @@ -2571,6 +2585,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, log.Errorf(err.Error()) key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2588,6 +2603,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, log.Errorf(err.Error()) key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2662,6 +2678,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, "%v", err) key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2741,6 +2758,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, errors.Is(err, ErrInvalidFundingOutput): key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2750,6 +2768,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, case errors.Is(err, ErrChannelSpent): key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2776,6 +2795,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, // edge. We won't increase the ban score for the // remote peer. key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2839,6 +2859,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, anns, rErr := d.processRejectedEdge(ctx, ann, proof) if rErr != nil { key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2866,6 +2887,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context, // Otherwise, this is just a regular rejected edge. key := newRejectCacheKey( + ann.GossipVersion(), scid.ToUint64(), sourceToPub(nMsg.source), ) @@ -2998,6 +3020,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(ctx context.Context, log.Errorf(err.Error()) key := newRejectCacheKey( + upd.GossipVersion(), upd.ShortChannelID.ToUint64(), sourceToPub(nMsg.source), ) @@ -3178,6 +3201,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(ctx context.Context, nMsg.err <- err key := newRejectCacheKey( + upd.GossipVersion(), upd.ShortChannelID.ToUint64(), sourceToPub(nMsg.source), ) @@ -3307,6 +3331,7 @@ func (d *AuthenticatedGossiper) handleChanUpdate(ctx context.Context, // Since we know the stored SCID in the graph, we'll // cache that SCID. key := newRejectCacheKey( + upd.GossipVersion(), chanInfo.ChannelID, sourceToPub(nMsg.source), ) diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 521e0896357..01faf5561c4 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -4717,6 +4717,7 @@ func TestChanAnnBanningNonChanPeer(t *testing.T) { // Remove the scid from the reject cache. key := newRejectCacheKey( + ca.GossipVersion(), ca.ShortChannelID.ToUint64(), sourceToPub(nodePeer2.IdentityKey()), ) From 54a5498207927d2c594d928d04373fa4a0b021ec Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Thu, 12 Jun 2025 14:24:52 +0200 Subject: [PATCH 12/19] channeldb: fix typo --- channeldb/waitingproof.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeldb/waitingproof.go b/channeldb/waitingproof.go index 0c3913f9bac..5ca8baea32b 100644 --- a/channeldb/waitingproof.go +++ b/channeldb/waitingproof.go @@ -195,7 +195,7 @@ type WaitingProof struct { isRemote bool } -// NewWaitingProof constructs a new waiting prof instance. +// NewWaitingProof constructs a new waiting proof instance. func NewWaitingProof(isRemote bool, proof *lnwire.AnnounceSignatures1) *WaitingProof { From 52764135856183ee81b59616f2e1ad04cee4b81a Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Thu, 12 Jun 2025 14:54:46 +0200 Subject: [PATCH 13/19] discovery: improve wording error message --- discovery/gossiper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 96a8c047ae3..f59ab3b6537 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -3475,7 +3475,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, if err != nil { _, err = d.cfg.FindChannel(nMsg.source, ann.ChannelID) if err != nil { - err := fmt.Errorf("unable to store the proof for "+ + err := fmt.Errorf("unable to find the channel for "+ "short_chan_id=%v: %v", shortChanID, err) log.Error(err) nMsg.err <- err From 0eb8dd53abe0f8f42de591dd0c3207d038022d8a Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Thu, 12 Jun 2025 16:44:13 +0200 Subject: [PATCH 14/19] discovery: use blank identifier when possible Use a blank identifier when values are intentionally unused. --- discovery/gossiper_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 01faf5561c4..5a4dd761fff 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -1573,7 +1573,7 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) { // channel through which it gets sent to control exactly when to // dispatch it. notifyPeers := make(chan chan<- lnpeer.Peer, 1) - tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(peer [33]byte, + tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte, connectedChan chan<- lnpeer.Peer) { notifyPeers <- connectedChan } @@ -1808,7 +1808,7 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { // Override NotifyWhenOnline to return the remote peer which we expect // meesages to be sent to. - tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(peer [33]byte, + tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte, peerChan chan<- lnpeer.Peer) { peerChan <- remotePeer @@ -2620,7 +2620,7 @@ func TestReceiveRemoteChannelUpdateFirst(t *testing.T) { // Override NotifyWhenOnline to return the remote peer which we expect // messages to be sent to. - tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(peer [33]byte, + tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte, peerChan chan<- lnpeer.Peer) { peerChan <- remotePeer From 9a33d37c6c77b80a8b1047fa28ef580d8d3ce60e Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Mon, 16 Jun 2025 17:48:00 +0200 Subject: [PATCH 15/19] lnwire+funding: constructors for ann. sigs two constructor funcs that create and return a pointer to an AnnounceSignatures1. `NewAnnSigFromSignature` takes `nodeSig` and `bitcoinSig` as pointers to `*ecdsa.Signature`. `NewAnnSigFromWireECDSA` takes those arguments in the raw 64-byte format we expect. --- funding/manager.go | 12 ++----- lnwire/announcement_signatures.go | 59 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/funding/manager.go b/funding/manager.go index 8176e6aa222..253180673f3 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -4634,15 +4634,9 @@ func (f *Manager) newChanAnnouncement(localPubKey, // Finally, we'll generate the announcement proof which we'll use to // provide the other side with the necessary signatures required to // allow them to reconstruct the full channel announcement. - proof := &lnwire.AnnounceSignatures1{ - ChannelID: chanID, - ShortChannelID: shortChanID, - } - proof.NodeSignature, err = lnwire.NewSigFromSignature(nodeSig) - if err != nil { - return nil, err - } - proof.BitcoinSignature, err = lnwire.NewSigFromSignature(bitcoinSig) + proof, err := lnwire.NewAnnSigFromSignature( + chanID, shortChanID, nodeSig, bitcoinSig, nil, + ) if err != nil { return nil, err } diff --git a/lnwire/announcement_signatures.go b/lnwire/announcement_signatures.go index 29ada700822..9b00d3f2897 100644 --- a/lnwire/announcement_signatures.go +++ b/lnwire/announcement_signatures.go @@ -3,6 +3,8 @@ package lnwire import ( "bytes" "io" + + "github.com/btcsuite/btcd/btcec/v2/ecdsa" ) // AnnounceSignatures1 is a direct message between two endpoints of a @@ -43,6 +45,63 @@ type AnnounceSignatures1 struct { ExtraOpaqueData ExtraOpaqueData } +func newAnnSig(chanID ChannelID, shortChanID ShortChannelID, + nodeSig, bitcoinSig Sig, + extraOpaqueData ExtraOpaqueData) *AnnounceSignatures1 { + + return &AnnounceSignatures1{ + ChannelID: chanID, + ShortChannelID: shortChanID, + NodeSignature: nodeSig, + BitcoinSignature: bitcoinSig, + ExtraOpaqueData: extraOpaqueData, + } +} + +// NewAnnSigFromSignature creates a new AnnounceSignatures1 message from the +// passed channel IDs, and `ecdsa.Signature` instances for the node and bitcoin +// keys. +func NewAnnSigFromSignature(chanID ChannelID, + shortChanID ShortChannelID, nodeSig, bitcoinSig *ecdsa.Signature, + extraOpaqueData ExtraOpaqueData) (*AnnounceSignatures1, error) { + + nodeSignature, err := NewSigFromSignature(nodeSig) + if err != nil { + return nil, err + } + bitcoinSignature, err := NewSigFromSignature(bitcoinSig) + if err != nil { + return nil, err + } + + return newAnnSig( + chanID, shortChanID, nodeSignature, bitcoinSignature, + extraOpaqueData, + ), nil +} + +// NewAnnSigFromWireECDSARaw creates a new AnnounceSignatures1 message from the +// passed channel IDs, and raw byte slices for the node and bitcoin key +// signatures. +func NewAnnSigFromWireECDSARaw(chanID ChannelID, + shortChanID ShortChannelID, nodeSig, bitcoinSig []byte, + extraOpaqueData ExtraOpaqueData) (*AnnounceSignatures1, error) { + + nodeSignature, err := NewSigFromECDSARawSignature(nodeSig) + if err != nil { + return nil, err + } + bitcoinSignature, err := NewSigFromECDSARawSignature(bitcoinSig) + if err != nil { + return nil, err + } + + return newAnnSig( + chanID, shortChanID, nodeSignature, bitcoinSignature, + extraOpaqueData, + ), nil +} + // A compile time check to ensure AnnounceSignatures1 implements the // lnwire.Message interface. var _ Message = (*AnnounceSignatures1)(nil) From 6dd32afcfb4b58f06c402404e03f13f26b3d972e Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Mon, 7 Jul 2025 14:16:42 +0200 Subject: [PATCH 16/19] discovery: add constructor for mockPeer --- discovery/gossiper_test.go | 130 +++++++++++++----------------- discovery/mock_test.go | 13 +++ discovery/reliable_sender_test.go | 5 +- 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 5a4dd761fff..77dc00b6bb1 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -960,7 +960,7 @@ func createTestCtx(t *testing.T, startHeight uint32, isChanPeer bool) ( peerChan chan<- lnpeer.Peer) { pk, _ := btcec.ParsePubKey(target[:]) - peerChan <- &mockPeer{pk, nil, nil, atomic.Bool{}} + peerChan <- newMockPeer(pk, nil, nil, false) }, NotifyWhenOffline: func(_ [33]byte) <-chan struct{} { c := make(chan struct{}) @@ -1043,7 +1043,7 @@ func TestProcessAnnouncement(t *testing.T) { } } - nodePeer := &mockPeer{remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // First, we'll craft a valid remote channel announcement and send it to // the gossiper so that it can be processed. @@ -1154,7 +1154,7 @@ func TestPrematureAnnouncement(t *testing.T) { _, err = createNodeAnnouncement(remoteKeyPriv1, timestamp) require.NoError(t, err, "can't create node announcement") - nodePeer := &mockPeer{remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // Pretending that we receive the valid channel announcement from // remote side, but block height of this announcement is greater than @@ -1194,9 +1194,9 @@ func TestSignatureAnnouncementLocalFirst(t *testing.T) { pk, _ := btcec.ParsePubKey(target[:]) select { - case peerChan <- &mockPeer{ - pk, sentMsgs, tCtx.gossiper.quit, atomic.Bool{}, - }: + case peerChan <- newMockPeer( + pk, sentMsgs, tCtx.gossiper.quit, false, + ): case <-tCtx.gossiper.quit: } } @@ -1206,9 +1206,9 @@ func TestSignatureAnnouncementLocalFirst(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{ - remoteKey, sentMsgs, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentMsgs, tCtx.gossiper.quit, false, + ) // Recreate lightning network topology. Initialize router with channel // between two nodes. @@ -1248,9 +1248,9 @@ func TestSignatureAnnouncementLocalFirst(t *testing.T) { case <-time.After(2 * trickleDelay): } - // The local ChannelUpdate should now be sent directly to the remote peer, - // such that the edge can be used for routing, regardless if this channel - // is announced or not (private channel). + // The local ChannelUpdate should now be sent directly to the remote + // peer, such that the edge can be used for routing, regardless if this + // channel is announced or not (private channel). select { case msg := <-sentMsgs: assertMessage(t, batch.chanUpdAnn1, msg) @@ -1373,9 +1373,9 @@ func TestOrphanSignatureAnnouncement(t *testing.T) { pk, _ := btcec.ParsePubKey(target[:]) select { - case peerChan <- &mockPeer{ - pk, sentMsgs, tCtx.gossiper.quit, atomic.Bool{}, - }: + case peerChan <- newMockPeer( + pk, sentMsgs, tCtx.gossiper.quit, false, + ): case <-tCtx.gossiper.quit: } } @@ -1385,9 +1385,9 @@ func TestOrphanSignatureAnnouncement(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{ - remoteKey, sentMsgs, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentMsgs, tCtx.gossiper.quit, false, + ) // Pretending that we receive local channel announcement from funding // manager, thereby kick off the announcement exchange process, in @@ -1460,9 +1460,9 @@ func TestOrphanSignatureAnnouncement(t *testing.T) { case <-time.After(2 * trickleDelay): } - // The local ChannelUpdate should now be sent directly to the remote peer, - // such that the edge can be used for routing, regardless if this channel - // is announced or not (private channel). + // The local ChannelUpdate should now be sent directly to the remote + // peer, such that the edge can be used for routing, regardless if this + // channel is announced or not (private channel). select { case msg := <-sentMsgs: assertMessage(t, batch.chanUpdAnn1, msg) @@ -1564,9 +1564,9 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) { // Set up a channel to intercept the messages sent to the remote peer. sentToPeer := make(chan lnwire.Message, 1) - remotePeer := &mockPeer{ - remoteKey, sentToPeer, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentToPeer, tCtx.gossiper.quit, false, + ) // Since the reliable send to the remote peer of the local channel proof // requires a notification when the peer comes online, we'll capture the @@ -1802,9 +1802,9 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { // Set up a channel we can use to inspect messages sent by the // gossiper to the remote peer. sentToPeer := make(chan lnwire.Message, 1) - remotePeer := &mockPeer{ - remoteKey, sentToPeer, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentToPeer, tCtx.gossiper.quit, false, + ) // Override NotifyWhenOnline to return the remote peer which we expect // meesages to be sent to. @@ -2002,7 +2002,7 @@ func TestDeDuplicatedAnnouncements(t *testing.T) { ) require.NoError(t, err, "can't create remote channel announcement") - nodePeer := &mockPeer{bitcoinKeyPub2, nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(bitcoinKeyPub2, nil, nil, false) announcements.AddMsgs(networkMsg{ msg: ca, peer: nodePeer, @@ -2293,7 +2293,7 @@ func TestForwardPrivateNodeAnnouncement(t *testing.T) { startingHeight - 1, ) require.NoError(t, err, "unable to create remote channel announcement") - peer := &mockPeer{pubKey, nil, nil, atomic.Bool{}} + peer := newMockPeer(pubKey, nil, nil, false) select { case err := <-tCtx.gossiper.ProcessRemoteAnnouncement( @@ -2614,9 +2614,9 @@ func TestReceiveRemoteChannelUpdateFirst(t *testing.T) { // Set up a channel that we can use to inspect the messages sent // directly from the gossiper. sentMsgs := make(chan lnwire.Message, 10) - remotePeer := &mockPeer{ - remoteKey, sentMsgs, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentMsgs, tCtx.gossiper.quit, false, + ) // Override NotifyWhenOnline to return the remote peer which we expect // messages to be sent to. @@ -2809,9 +2809,7 @@ func TestExtraDataChannelAnnouncementValidation(t *testing.T) { tCtx, err := createTestCtx(t, 0, false) require.NoError(t, err, "can't create context") - remotePeer := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + remotePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // We'll now create an announcement that contains an extra set of bytes // that we don't know of ourselves, but should still include in the @@ -2847,9 +2845,7 @@ func TestExtraDataChannelUpdateValidation(t *testing.T) { tCtx, err := createTestCtx(t, 0, false) require.NoError(t, err, "can't create context") - remotePeer := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + remotePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // In this scenario, we'll create two announcements, one regular // channel announcement, and another channel update announcement, that @@ -2907,9 +2903,7 @@ func TestExtraDataNodeAnnouncementValidation(t *testing.T) { tCtx, err := createTestCtx(t, 0, false) require.NoError(t, err, "can't create context") - remotePeer := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + remotePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) timestamp := testTimestamp // We'll create a node announcement that includes a set of opaque data @@ -2985,7 +2979,7 @@ func TestRetransmit(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{remoteKey, nil, nil, atomic.Bool{}} + remotePeer := newMockPeer(remoteKey, nil, nil, false) // Process a local channel announcement, channel update and node // announcement. No messages should be broadcasted yet, since no proof @@ -3095,7 +3089,7 @@ func TestNodeAnnouncementNoChannels(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{remoteKey, nil, nil, atomic.Bool{}} + remotePeer := newMockPeer(remoteKey, nil, nil, false) // Process the remote node announcement. select { @@ -3186,7 +3180,7 @@ func TestOptionalFieldsChannelUpdateValidation(t *testing.T) { chanUpdateHeight := uint32(0) timestamp := uint32(123456) - nodePeer := &mockPeer{remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // In this scenario, we'll test whether the message flags field in a // channel update is properly handled. @@ -3294,9 +3288,9 @@ func TestSendChannelUpdateReliably(t *testing.T) { // Set up a channel we can use to inspect messages sent by the // gossiper to the remote peer. sentToPeer := make(chan lnwire.Message, 1) - remotePeer := &mockPeer{ - remoteKey, sentToPeer, tCtx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer( + remoteKey, sentToPeer, tCtx.gossiper.quit, false, + ) // Since we first wait to be notified of the peer before attempting to // send the message, we'll overwrite NotifyWhenOnline and @@ -3652,9 +3646,7 @@ func TestPropagateChanPolicyUpdate(t *testing.T) { remoteKey := remoteKeyPriv1.PubKey() sentMsgs := make(chan lnwire.Message, 10) - remotePeer := &mockPeer{ - remoteKey, sentMsgs, ctx.gossiper.quit, atomic.Bool{}, - } + remotePeer := newMockPeer(remoteKey, sentMsgs, ctx.gossiper.quit, false) // The forced code path for sending the private ChannelUpdate to the // remote peer will be hit, forcing it to request a notification that @@ -4007,9 +3999,9 @@ func TestBroadcastAnnsAfterGraphSynced(t *testing.T) { t.Helper() - nodePeer := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer := newMockPeer( + remoteKeyPriv1.PubKey(), nil, nil, false, + ) var errChan chan error if isRemote { errChan = tCtx.gossiper.ProcessRemoteAnnouncement( @@ -4109,9 +4101,7 @@ func TestRateLimitDeDup(t *testing.T) { batch, err := tCtx.createRemoteAnnouncements(blockHeight) require.NoError(t, err) - nodePeer1 := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer1 := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) select { case err := <-tCtx.gossiper.ProcessRemoteAnnouncement( ctx, batch.chanAnn, nodePeer1, @@ -4130,9 +4120,7 @@ func TestRateLimitDeDup(t *testing.T) { t.Fatal("remote announcement not processed") } - nodePeer2 := &mockPeer{ - remoteKeyPriv2.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer2 := newMockPeer(remoteKeyPriv2.PubKey(), nil, nil, false) select { case err := <-tCtx.gossiper.ProcessRemoteAnnouncement( ctx, batch.chanUpdAnn2, nodePeer2, @@ -4287,9 +4275,7 @@ func TestRateLimitChannelUpdates(t *testing.T) { batch, err := tCtx.createRemoteAnnouncements(blockHeight) require.NoError(t, err) - nodePeer1 := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer1 := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) select { case err := <-tCtx.gossiper.ProcessRemoteAnnouncement( ctx, batch.chanAnn, nodePeer1, @@ -4308,9 +4294,7 @@ func TestRateLimitChannelUpdates(t *testing.T) { t.Fatal("remote announcement not processed") } - nodePeer2 := &mockPeer{ - remoteKeyPriv2.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer2 := newMockPeer(remoteKeyPriv2.PubKey(), nil, nil, false) select { case err := <-tCtx.gossiper.ProcessRemoteAnnouncement( ctx, batch.chanUpdAnn2, nodePeer2, @@ -4432,7 +4416,7 @@ func TestIgnoreOwnAnnouncement(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{remoteKey, nil, nil, atomic.Bool{}} + remotePeer := newMockPeer(remoteKey, nil, nil, false) // Try to let the remote peer tell us about the channel we are part of. select { @@ -4581,7 +4565,7 @@ func TestRejectCacheChannelAnn(t *testing.T) { remoteKey, err := btcec.ParsePubKey(batch.nodeAnn2.NodeID[:]) require.NoError(t, err, "unable to parse pubkey") - remotePeer := &mockPeer{remoteKey, nil, nil, atomic.Bool{}} + remotePeer := newMockPeer(remoteKey, nil, nil, false) // Before sending over the announcement, we'll modify it such that we // know it will always fail. @@ -4655,12 +4639,8 @@ func TestChanAnnBanningNonChanPeer(t *testing.T) { tCtx, err := createTestCtx(t, 1000, false) require.NoError(t, err, "can't create context") - nodePeer1 := &mockPeer{ - remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}, - } - nodePeer2 := &mockPeer{ - remoteKeyPriv2.PubKey(), nil, nil, atomic.Bool{}, - } + nodePeer1 := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) + nodePeer2 := newMockPeer(remoteKeyPriv2.PubKey(), nil, nil, false) // Loop 100 times to get nodePeer banned. for i := range DefaultBanThreshold { @@ -4751,7 +4731,7 @@ func TestChanAnnBanningChanPeer(t *testing.T) { tCtx, err := createTestCtx(t, 1000, true) require.NoError(t, err, "can't create context") - nodePeer := &mockPeer{remoteKeyPriv1.PubKey(), nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(remoteKeyPriv1.PubKey(), nil, nil, false) // Loop 100 times to get nodePeer banned. for i := range DefaultBanThreshold { @@ -4828,7 +4808,7 @@ func assertChanChainRejection(t *testing.T, ctx *testCtx, t.Helper() - nodePeer := &mockPeer{bitcoinKeyPub2, nil, nil, atomic.Bool{}} + nodePeer := newMockPeer(bitcoinKeyPub2, nil, nil, false) errChan := make(chan error, 1) nMsg := &networkMsg{ msg: edge, diff --git a/discovery/mock_test.go b/discovery/mock_test.go index 6bd93c29b73..874eadce5ca 100644 --- a/discovery/mock_test.go +++ b/discovery/mock_test.go @@ -23,6 +23,19 @@ type mockPeer struct { var _ lnpeer.Peer = (*mockPeer)(nil) +func newMockPeer(pk *btcec.PublicKey, sentMsgs chan lnwire.Message, + quit chan struct{}, disconnected bool) *mockPeer { + + p := &mockPeer{ + pk: pk, + sentMsgs: sentMsgs, + quit: quit, + } + p.disconnected.Store(disconnected) + + return p +} + func (p *mockPeer) SendMessage(_ bool, msgs ...lnwire.Message) error { if p.sentMsgs == nil && p.quit == nil { return nil diff --git a/discovery/reliable_sender_test.go b/discovery/reliable_sender_test.go index 32a9908c748..a1879743e12 100644 --- a/discovery/reliable_sender_test.go +++ b/discovery/reliable_sender_test.go @@ -3,7 +3,6 @@ package discovery import ( "context" "fmt" - "sync/atomic" "testing" "time" @@ -78,7 +77,7 @@ func TestReliableSenderFlow(t *testing.T) { // Create a mock peer to send the messages to. pubKey := randPubKey(t) msgsSent := make(chan lnwire.Message) - peer := &mockPeer{pubKey, msgsSent, reliableSender.quit, atomic.Bool{}} + peer := newMockPeer(pubKey, msgsSent, reliableSender.quit, false) // Override NotifyWhenOnline and NotifyWhenOffline to provide the // notification channels so that we can control when notifications get @@ -195,7 +194,7 @@ func TestReliableSenderStaleMessages(t *testing.T) { // Create a mock peer to send the messages to. pubKey := randPubKey(t) msgsSent := make(chan lnwire.Message) - peer := &mockPeer{pubKey, msgsSent, reliableSender.quit, atomic.Bool{}} + peer := newMockPeer(pubKey, msgsSent, reliableSender.quit, false) // Override NotifyWhenOnline to provide the notification channel so that // we can control when notifications get dispatched. From 511be4c112bd219f45965f8fdc97513f6730c1e7 Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Mon, 16 Jun 2025 17:51:23 +0200 Subject: [PATCH 17/19] discovery: send sig ann when full proof available We change the discovery gossiper to send a signature announcement in response to receiving a signature announcement, but only if the full proof is available. Previously the behavior was to send the channel announcement. --- discovery/gossiper.go | 38 +++++++++++++++++++++++++++----------- discovery/gossiper_test.go | 6 +++--- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index f59ab3b6537..5dda7e008d8 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -3542,7 +3542,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, if chanInfo.AuthProof != nil { // If we already have the fully assembled proof, then the peer // sending us their proof has probably not received our local - // proof yet. So be kind and send them the full proof. + // proof yet. So be kind and send them our proof. if nMsg.isRemote { peerID := nMsg.source.SerializeCompressed() log.Debugf("Got AnnounceSignatures for channel with " + @@ -3553,28 +3553,44 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, defer d.wg.Done() log.Debugf("Received half proof for channel "+ - "%v with existing full proof. Sending"+ - " full proof to peer=%x", + "%v with existing full proof. Sending "+ + "announcement signatures to peer=%x", ann.ChannelID, peerID) - ca, _, _, err := netann.CreateChanAnnouncement( - chanInfo.AuthProof, chanInfo, e1, e2, + chanAP := chanInfo.AuthProof + var remoteNSB []byte + var remoteBSB []byte + if isFirstNode { + remoteNSB = chanAP.NodeSig2Bytes + remoteBSB = chanAP.BitcoinSig2Bytes + } else { + remoteNSB = chanAP.NodeSig1Bytes + remoteBSB = chanAP.BitcoinSig1Bytes + } + + sigAnn, err := lnwire.NewAnnSigFromWireECDSARaw( + ann.ChannelID, ann.ShortChannelID, + remoteNSB, remoteBSB, nil, ) + if err != nil { - log.Errorf("unable to gen ann: %v", + log.Errorf("Failed to generate "+ + "announcement signature: %v", err) return } - err = nMsg.peer.SendMessage(false, ca) + err = nMsg.peer.SendMessage(false, sigAnn) if err != nil { - log.Errorf("Failed sending full proof"+ - " to peer=%x: %v", peerID, err) + log.Errorf("Failed sending signature "+ + "announcement to peer=%x: %v", + peerID, err) return } - log.Debugf("Full proof sent to peer=%x for "+ - "chanID=%v", peerID, ann.ChannelID) + log.Debugf("Signature announcement sent to "+ + "peer=%x for chanID=%v", peerID, + ann.ChannelID) }() } diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index 77dc00b6bb1..d75ff549567 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -1949,7 +1949,7 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { } // Now give the gossiper the remote proof yet again. This should - // trigger a send of the full ChannelAnnouncement. + // trigger a send of the signature announcement. select { case err = <-tCtx.gossiper.ProcessRemoteAnnouncement( ctx, batch.remoteProofAnn, remotePeer, @@ -1962,9 +1962,9 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { // We expect the gossiper to send this message to the remote peer. select { case msg := <-sentToPeer: - _, ok := msg.(*lnwire.ChannelAnnouncement1) + _, ok := msg.(*lnwire.AnnounceSignatures1) if !ok { - t.Fatalf("expected ChannelAnnouncement1, instead got "+ + t.Fatalf("expected AnnounceSignatures1, instead got "+ "%T", msg) } case <-time.After(2 * time.Second): From 9402ec994a6761283f62386fd28d89a49eae7749 Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Mon, 16 Jun 2025 23:14:27 +0200 Subject: [PATCH 18/19] discovery: send signature announcement once This change aligns our behavior with latest protocol guidelines. That is, when we receive a signature announcement when we already have the full proof we reply with our signature announcement once per (re)connection. see: https://github.com/lightning/bolts/pull/1256 --- discovery/gossiper.go | 126 +++++++++++++++++++++++++++++++++---- discovery/gossiper_test.go | 101 ++++++++++++++++++++++++----- 2 files changed, 197 insertions(+), 30 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 5dda7e008d8..00444142e10 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -473,6 +473,60 @@ func (c *cachedReject) Size() (uint64, error) { return 1, nil } +// sentAnnSigsTracker tracks which announcement signatures we've sent to which +// peers. +type sentAnnSigsTracker struct { + mu sync.Mutex + sigs map[route.Vertex]map[lnwire.ChannelID]struct{} +} + +// newSentAnnSigsTracker creates a new sentAnnSigsTracker. +func newSentAnnSigsTracker() *sentAnnSigsTracker { + return &sentAnnSigsTracker{ + sigs: make(map[route.Vertex]map[lnwire.ChannelID]struct{}), + } +} + +// deletePeer deletes all records of sent announcement signatures for a given +// peer. +func (s *sentAnnSigsTracker) deletePeer(peer route.Vertex) { + s.mu.Lock() + defer s.mu.Unlock() + delete(s.sigs, peer) +} + +// sentToPeer returns true if we have already sent the announcement signature +// for a given channel to a peer. +func (s *sentAnnSigsTracker) sentToPeer(peer route.Vertex, + cid lnwire.ChannelID) bool { + + s.mu.Lock() + defer s.mu.Unlock() + + sentChans, ok := s.sigs[peer] + if !ok { + return false + } + + _, ok = sentChans[cid] + + return ok +} + +// addToPeer adds a record of sending an announcement signature for a given +// channel to a peer. +func (s *sentAnnSigsTracker) addToPeer(peer route.Vertex, + cid lnwire.ChannelID) { + + s.mu.Lock() + defer s.mu.Unlock() + + if _, ok := s.sigs[peer]; !ok { + s.sigs[peer] = make(map[lnwire.ChannelID]struct{}) + } + s.sigs[peer][cid] = struct{}{} +} + // AuthenticatedGossiper is a subsystem which is responsible for receiving // announcements, validating them and applying the changes to router, syncing // lightning network with newly connected nodes, broadcasting announcements @@ -568,6 +622,11 @@ type AuthenticatedGossiper struct { // vb is used to enforce job dependency ordering of gossip messages. vb *ValidationBarrier + // sentAnnSigs tracks which announcement signatures we've sent to which + // peers. We'll use this to ensure we don't re-send the same signatures + // to a peer during a single connection. + sentAnnSigs *sentAnnSigsTracker + sync.Mutex cancel fn.Option[context.CancelFunc] @@ -595,6 +654,7 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper ), chanUpdateRateLimiter: make(map[uint64][2]*rate.Limiter), banman: newBanman(cfg.BanThreshold), + sentAnnSigs: newSentAnnSigsTracker(), } gossiper.vb = NewValidationBarrier(1000, gossiper.quit) @@ -1677,6 +1737,14 @@ func (d *AuthenticatedGossiper) handleNetworkMessages(ctx context.Context, // queries. We'll allocate a new gossip syncer for it, and start any goroutines // needed to handle new queries. func (d *AuthenticatedGossiper) InitSyncState(syncPeer lnpeer.Peer) { + peerVertex := route.NewVertex(syncPeer.IdentityKey()) + + // We keep track if we already have sent an announcement signature to + // each peer during a connection, so we don't send it twice. If a peer + // dis- and reconnects we clear the record. If the peer connects for the + // first time this is a no-op. + d.sentAnnSigs.deletePeer(peerVertex) + d.syncMgr.InitSyncState(syncPeer) } @@ -3542,12 +3610,26 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, if chanInfo.AuthProof != nil { // If we already have the fully assembled proof, then the peer // sending us their proof has probably not received our local - // proof yet. So be kind and send them our proof. + // proof yet. So be kind and send them our proof, but only if we + // haven't done so since (re)connecting. if nMsg.isRemote { - peerID := nMsg.source.SerializeCompressed() - log.Debugf("Got AnnounceSignatures for channel with " + - "full proof.") + peerVertex := route.NewVertex(nMsg.source) + + if d.sentAnnSigs.sentToPeer(peerVertex, ann.ChannelID) { + log.Debugf("Skipping sending " + + "announcement signatures " + + "since we already did during " + + "this connection.") + nMsg.err <- nil + + return nil, true + } + + peerID := nMsg.source.SerializeCompressed() + peerIsFirstNode := bytes.Equal( + peerID, chanInfo.NodeKey1Bytes[:], + ) d.wg.Add(1) go func() { defer d.wg.Done() @@ -3558,21 +3640,28 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, ann.ChannelID, peerID) chanAP := chanInfo.AuthProof - var remoteNSB []byte - var remoteBSB []byte - if isFirstNode { - remoteNSB = chanAP.NodeSig2Bytes - remoteBSB = chanAP.BitcoinSig2Bytes + // Pick the local signatures that the peer does + // NOT have yet. If the peer is node1, they sent + // us node1/bitcoin1 already, so we respond with + // node2/bitcoin2. Otherwise we respond with + // node1/bitcoin1. + var localNSB, localBSB []byte + if peerIsFirstNode { + localNSB = chanAP.NodeSig2Bytes + localBSB = chanAP.BitcoinSig2Bytes } else { - remoteNSB = chanAP.NodeSig1Bytes - remoteBSB = chanAP.BitcoinSig1Bytes + localNSB = chanAP.NodeSig1Bytes + localBSB = chanAP.BitcoinSig1Bytes } + // Construct an AnnounceSignatures message from + // the raw signature material. This gives the + // peer our half of the proof so they can + // assemble the full ChannelAnnouncement. sigAnn, err := lnwire.NewAnnSigFromWireECDSARaw( ann.ChannelID, ann.ShortChannelID, - remoteNSB, remoteBSB, nil, + localNSB, localBSB, nil, ) - if err != nil { log.Errorf("Failed to generate "+ "announcement signature: %v", @@ -3580,6 +3669,10 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, return } + // Send our half of the proof to the peer. If + // successful, we mark that we've sent the proof + // during this connection so we don't re-send it + // on subsequent half-proof messages. err = nMsg.peer.SendMessage(false, sigAnn) if err != nil { log.Errorf("Failed sending signature "+ @@ -3588,6 +3681,13 @@ func (d *AuthenticatedGossiper) handleAnnSig(ctx context.Context, return } + // With the announcement sent, we'll now mark + // that we've sent the proof to the peer for + // this connection. + d.sentAnnSigs.addToPeer( + peerVertex, ann.ChannelID, + ) + log.Debugf("Signature announcement sent to "+ "peer=%x for chanID=%v", peerID, ann.ChannelID) diff --git a/discovery/gossiper_test.go b/discovery/gossiper_test.go index d75ff549567..d1dc5f4c3a8 100644 --- a/discovery/gossiper_test.go +++ b/discovery/gossiper_test.go @@ -1783,16 +1783,23 @@ out: } } -// TestSignatureAnnouncementFullProofWhenRemoteProof tests that if a remote +// TestSignatureAnnouncementResendWhenRemoteProof tests that if a remote // proof is received when we already have the full proof, the gossiper will send -// the full proof (ChannelAnnouncement) to the remote peer. -func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { +// our signature announcement max once per connection to the remote peer. +func TestSignatureAnnouncementResendWhenRemoteProof(t *testing.T) { t.Parallel() ctx := t.Context() tCtx, err := createTestCtx(t, proofMatureDelta, false) require.NoError(t, err, "can't create context") + // We'll create our test sync manager to have one active syncer. + syncMgr := newTestSyncManager(1) + syncMgr.Start() + defer syncMgr.Stop() + + tCtx.gossiper.syncMgr = syncMgr + batch, err := tCtx.createLocalAnnouncements(0) require.NoError(t, err, "can't generate announcements") @@ -1806,8 +1813,15 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { remoteKey, sentToPeer, tCtx.gossiper.quit, false, ) + // We create an active syncer for our remote peer. + tCtx.gossiper.InitSyncState(remotePeer) + remoteSyncer := assertSyncerExistence(t, syncMgr, remotePeer) + assertTransitionToChansSynced(t, remoteSyncer, remotePeer) + assertActiveGossipTimestampRange(t, remotePeer) + assertSyncerStatus(t, remoteSyncer, chansSynced, ActiveSync) + // Override NotifyWhenOnline to return the remote peer which we expect - // meesages to be sent to. + // messages to be sent to. tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte, peerChan chan<- lnpeer.Peer) { @@ -1905,14 +1919,25 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { } require.NoError(t, err, "unable to process local proof") - select { - case err = <-tCtx.gossiper.ProcessRemoteAnnouncement( - ctx, batch.remoteProofAnn, remotePeer, - ): - case <-time.After(2 * time.Second): - t.Fatal("did not process local announcement") + // Define helper to process a remote proof in a sub-test. + processRemoteProof := func(t *testing.T) { + t.Helper() + var err error + select { + case err = <-tCtx.gossiper.ProcessRemoteAnnouncement( + ctx, batch.remoteProofAnn, remotePeer, + ): + case <-time.After(2 * time.Second): + t.Fatal("did not process local announcement") + } + require.NoError(t, err, "unable to process remote proof") } - require.NoError(t, err, "unable to process remote proof") + + // Now give the gossiper the remote proof. This should + // trigger a send of our signature announcement. + t.Run("process remote proof - first send", func(t *testing.T) { + processRemoteProof(t) + }) // We expect the gossiper to send this message to the remote peer. select { @@ -1949,15 +1974,57 @@ func TestSignatureAnnouncementFullProofWhenRemoteProof(t *testing.T) { } // Now give the gossiper the remote proof yet again. This should - // trigger a send of the signature announcement. + // trigger a send of our signature announcement. + t.Run("process remote proof - first resend", func(t *testing.T) { + processRemoteProof(t) + }) + + // We expect the gossiper to send this message to the remote peer. select { - case err = <-tCtx.gossiper.ProcessRemoteAnnouncement( - ctx, batch.remoteProofAnn, remotePeer, - ): + case msg := <-sentToPeer: + _, ok := msg.(*lnwire.AnnounceSignatures1) + if !ok { + t.Fatalf("expected AnnounceSignatures1, instead got "+ + "%T", msg) + } case <-time.After(2 * time.Second): - t.Fatal("did not process local announcement") + t.Fatal("did not send local proof to peer") } - require.NoError(t, err, "unable to process remote proof") + + // Now give the gossiper the remote proof yet again. This should + // **not** trigger a send of our signature announcement. + t.Run("process remote proof - second resend", func(t *testing.T) { + processRemoteProof(t) + }) + + // We expect the gossiper to _not_ send this message to the remote peer. + select { + case msg := <-sentToPeer: + _, ok := msg.(*lnwire.AnnounceSignatures1) + if ok { + t.Fatalf("got an AnnounceSignatures1 when none was "+ + "expected %T", msg) + } + case <-time.After(2 * time.Second): + break + } + + // We prune the syncer, simulating the remote peer having disconnected. + tCtx.gossiper.PruneSyncState(remotePeer.PubKey()) + + // We simulate the remote peer coming back online. + tCtx.gossiper.InitSyncState(remotePeer) + remoteSyncer1 := assertSyncerExistence(t, syncMgr, remotePeer) + assertTransitionToChansSynced(t, remoteSyncer1, remotePeer) + assertActiveGossipTimestampRange(t, remotePeer) + assertSyncerStatus(t, remoteSyncer1, chansSynced, ActiveSync) + + // Now give the gossiper the remote proof yet again. This should trigger + // a send of our signature announcement, because we are now on a new + // connection. + t.Run("process remote proof - third resend", func(t *testing.T) { + processRemoteProof(t) + }) // We expect the gossiper to send this message to the remote peer. select { From 2e601d8740a51f10eddfaf9ac6d75d4dc3305535 Mon Sep 17 00:00:00 2001 From: Gijs van Dam Date: Wed, 8 Oct 2025 17:31:55 +0200 Subject: [PATCH 19/19] docs: update release notes for 0.21.0 --- docs/release-notes/release-notes-0.21.0.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/release-notes/release-notes-0.21.0.md b/docs/release-notes/release-notes-0.21.0.md index 9749b580763..7a0ae757dbf 100644 --- a/docs/release-notes/release-notes-0.21.0.md +++ b/docs/release-notes/release-notes-0.21.0.md @@ -44,6 +44,11 @@ # Technical and Architectural Updates ## BOLT Spec Updates +* Re-send the [AnnouncementSignature max + once](https://github.com/lightningnetwork/lnd/pull/9957) per (re)connection + when we already have the full proof and our peer sends us their signature + announcement. + ## Testing ## Database