Skip to content

lint: enable iface and revive, drop maintidx - #2193

Merged
AkramBitar merged 1 commit into
LFDT-Panurus:mainfrom
atharrva01:fix/enable-iface
Aug 13, 2026
Merged

lint: enable iface and revive, drop maintidx#2193
AkramBitar merged 1 commit into
LFDT-Panurus:mainfrom
atharrva01:fix/enable-iface

Conversation

@atharrva01

Copy link
Copy Markdown
Contributor

Next step of #1991, after #2114. Covers iface, plus the two you were waiting on me to ask
about, maintidx and revive. I went ahead and made the call on both rather than leave them
blocked, happy to change either.

Measured each linter on its own this time, uncapped, across every module in GO_MODULES.

iface

95 issues: 66 unused, 17 opaque, 12 identical. Enabled with only identical.

unused is disabled. It only looks inside the declaring package, and the driver pattern
puts SPI interfaces in dedicated driver and api packages that are implemented and consumed
from other modules, so they are unused at home by construction. I counted cross-package
references for all 66: 61 are referenced by between 1 and 79 files elsewhere in the tree,
driver.Driver among them. Five had none and were genuinely dead:

interface package
Agent network/fabric/tcc
ChannelMSPManager network/fabricx/endorsement
Collector nwo/txgen/service/metrics
FSCPlatform nwo/token/generators/crypto/fabtokenv1
TokenNotifierDriver storage/db/driver

Deleted. ChannelMSPManagerProvider also still claimed in its comment to resolve a
ChannelMSPManager while actually returning fsc.MSPManager, so that comment is fixed.

opaque is disabled. It wants constructors to return their concrete type, but in 14 of its
17 reports that type is unexported, so callers could not name the result and revive's
unexported-return rule in the same config would reject it. One is impossible outright: the
concrete type is lazy.lazyProvider, an unexported generic in fabric-smart-client. The two
exported ones are NewQuantityFromUInt64, a deliberate member of the polymorphic Quantity
constructor family next to ToQuantity, and NewIdemixCASupport.

identical is enabled. Six pairs, three real:

  • htlc.Vault and multisig.Vault are byte-identical duplicates of TokenVault in the same
    file, and nothing referenced either of them. Deleted.
  • driver.ValidatorLedger has the same method set as driver.Ledger, and two references
    against Ledger's 54, one of which is the token.Ledger alias. Its generated mock was
    identical to mock.Ledger modulo the name. Merged into Ledger, mock deleted,
    token.Ledger now aliases driver.Ledger. A stray duplicate counterfeiter directive for
    Validator went with it.

The other three are deliberate and carry a specific nolint with the reason: Input and
LedgerToken are different concepts that happen to share GetOwner, CleanupLeadership and
RecoveryLeadership are parallel on purpose because the two take different advisory locks, and
TransactionDB and AuditDB are separate DI bindings resolved by type.

revive

Enabled, but not with enable-all-rules. That reports 3452 issues over 688 files, which is
not reviewable in one change. The config now lists 38 rules explicitly, all already clean
tree-wide, so revive lands as a ratchet against new code rather than as a backlog. Four fixes
were needed to get there, one comment spacing in a zkatdlog test and three in txgen's
error.go.

The rules left out are listed in a comment in the config with their current counts so the next
step does not have to re-measure. The big ones:

rule issues
exported 1568
unused-parameter 362
unused-receiver 334
import-shadowing 328
unchecked-type-assertion 125
argument-limit 103

Three more are left out because another enabled linter already covers them (line-length-limit
by lll, imports-blocklist by depguard, file-header by goheader) and six because they
are no-ops at their default settings.

Dropping enable-all-rules also removes the nine disabled: true entries, which only existed
to switch rules back off, and argument-limit and function-result-limit, which were tuned but
have 103 and 49 violations and so belong with the deferred set.

maintidx

Settings block deleted rather than enabled. It reports 19 functions and every one would have to
be suppressed: 12 in _test.go, 4 in the shared testutils and dbtest helpers, 1 is Prove
in the CSP range proof, and 2 are the fungible suite entry point and its topology. The score is
driven by Halstead volume, so a long table-driven test or a flat block of declarative topology
wiring scores badly for being long rather than for being tangled, and table-driven tests are the
style AGENTS.md asks for. A linter that starts at a 100% suppression rate is measuring the wrong
thing here. gocognit is still configured and unenabled, and at min-complexity: 15 it targets
branching directly, which is the check actually wanted.

I tried it the other way first, with path exclusions for tests plus nolints on the rest. It
worked, but warn-unused: true then logs an unused-exclusion warning in the seven modules where
the paths do not match, so it traded 19 suppressions for noise in every other module.

After this

gocognit and wrapcheck are the only settings blocks left for linters that are not enabled.

golangci-lint run is clean on all nine modules, make checks passes, and tests pass on the
touched packages.

Deleting the seven exported interfaces is a breaking change for anyone referencing them out of
tree.

@AkramBitar AkramBitar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Approved.

@AkramBitar

Copy link
Copy Markdown
Contributor

@atharrva01 could you please rebase and squash your commits to one?
Also, I am wondering why the coverage went down.

@atharrva01

Copy link
Copy Markdown
Contributor Author

On the two Coveralls failures in the last run, I don't think they came from this change.

Nothing here adds or removes a coverable statement. Every deletion is an interface
declaration, a comment or an import, and Go's instrumentation only counts statements. I built
the coverage block inventory for all eight touched packages on both commits to check: 3129
statements either way, identical per file.

The one deleted file with real statements is the ValidatorLedger mock, and
ci/scripts/filter-coverage.sh strips /mock/ paths before upload, so it never reaches
Coveralls at all. The txgen error.go fix gets dropped by the /integration/ rule for the
same reason.

Both flags also move around by roughly a point on unrelated PRs:

job range over the last ~19 merged PRs this run
itest-dloghsm-fabric-t2-replicas 43.24 to 44.69% 43.57%
itest-fabtoken-fabric-t1-replicas 35.14 to 36.21% 34.68%

43.57% is inside that range and above #2174, which passed. These are the -replicas variants,
so how much of the leader election and recovery sweep code gets exercised depends on timing.
The aggregate coverage/coveralls check went up slightly on the same build.

The branch was also 9 commits behind main, so the base build it compared against was stale.
I've rebased and squashed to a single commit, which at least gives Coveralls a current base.
If it dips again there's nothing in the diff I can change to move it.

@AkramBitar
AkramBitar force-pushed the fix/enable-iface branch 3 times, most recently from 46d428a to 7d47f6f Compare August 12, 2026 17:25
Next step of LFDT-Panurus#1991, after LFDT-Panurus#2114. Covers iface, plus maintidx and revive, the two that were
left open. I made the call on both rather than leave them blocked, happy to change either.

Each linter was measured on its own, uncapped, across every module in GO_MODULES.

iface reports 95 issues: 66 unused, 17 opaque, 12 identical. Enabled with only identical.

unused only looks inside the declaring package. The driver pattern puts SPI interfaces in
dedicated driver and api packages that are implemented and consumed from other modules, so
they are unused at home by construction. I counted cross-package references for all 66: 61
are referenced by between 1 and 79 files elsewhere in the tree, driver.Driver among them.
Five had none and were genuinely dead, deleted here:

  tcc.Agent
  endorsement.ChannelMSPManager
  metrics.Collector
  fabtokenv1.FSCPlatform
  driver.TokenNotifierDriver

ChannelMSPManagerProvider still claimed in its comment to resolve a ChannelMSPManager while
actually returning fsc.MSPManager, so that comment is corrected too.

opaque wants a constructor to return its concrete type, but in 14 of its 17 reports that
type is unexported, so callers could not name the result and revive's unexported-return rule
in the same config would reject it. One is impossible outright: the concrete type is
lazy.lazyProvider, an unexported generic in fabric-smart-client. The two exported ones are
NewQuantityFromUInt64, a deliberate member of the polymorphic Quantity constructor family
next to ToQuantity, and NewIdemixCASupport.

identical reports six pairs. Three are real:

  htlc.Vault and multisig.Vault are byte-identical duplicates of TokenVault in the same file
  and nothing referenced either of them, so both are deleted.

  driver.ValidatorLedger has the same method set as driver.Ledger and two references against
  Ledger's 54, one of them the token.Ledger alias. Its generated mock was identical to
  mock.Ledger modulo the name. Merged into Ledger, mock deleted, token.Ledger now aliases
  driver.Ledger. A stray duplicate counterfeiter directive for Validator went with it.

Three are deliberate and carry a specific nolint with the reason: Input and LedgerToken are
different concepts that happen to share GetOwner, CleanupLeadership and RecoveryLeadership
are parallel on purpose because the two take different advisory locks, and TransactionDB and
AuditDB are separate DI bindings resolved by type.

revive is enabled, but not with enable-all-rules. That reports 3452 issues over 688 files,
which is not something anyone can review in one go. The config now lists 38 rules explicitly,
all of which are already clean tree-wide, so revive lands as a ratchet against new code rather
than as a backlog. Four fixes were needed to get there: one comment spacing in a zkatdlog test
and three in txgen's error.go.

The rules left out are named in a comment in the config with their current counts, so the next
step does not have to re-measure. The big ones are exported (1568), unused-parameter (362),
unused-receiver (334) and import-shadowing (328). Three more are left out because another
enabled linter already covers them, line-length-limit by lll, imports-blocklist by depguard,
file-header by goheader, and six because they are no-ops at their default settings.

Dropping enable-all-rules also removes the nine "disabled: true" entries, which only existed
to switch rules back off, and argument-limit and function-result-limit, which were tuned but
have 103 and 49 violations and so belong with the deferred set.

maintidx has its settings block deleted rather than enabled. It reports 19 functions and every
one of them would have to be suppressed: 12 are in _test.go, 4 are in the shared testutils and
dbtest helpers, 1 is Prove in the CSP range proof, and 2 are the fungible suite entry point and
its topology. The score is driven by Halstead volume, so a long table-driven test or a flat
block of declarative topology wiring scores badly for being long rather than for being tangled,
and table-driven tests are the style AGENTS.md asks for. A linter that starts at a 100%
suppression rate is measuring the wrong thing here. gocognit is still configured and unenabled,
and at min-complexity 15 it targets branching directly, which is the check actually wanted.

I tried it the other way first, with path exclusions for tests plus nolints on the rest. It
worked, but warn-unused: true then logs an unused-exclusion warning in the seven modules where
the paths do not match, so it traded 19 suppressions for noise in every other module.

That leaves gocognit and wrapcheck as the only settings blocks for linters that are not enabled.

golangci-lint run is clean on all nine modules, make checks passes, and tests pass on the
touched packages.

Deleting the seven exported interfaces is a breaking change for anyone referencing them out of
tree.

Signed-off-by: atharrva01 <atharvaborade568@gmail.com>
@AkramBitar
AkramBitar merged commit 2a9d181 into LFDT-Panurus:main Aug 13, 2026
149 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants