diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4cf7bb0aac..743a084532 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,19 +15,7 @@ on: jobs: lint: name: Lint - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version-file: 'go.mod' - - name: golangci-lint - uses: golangci/golangci-lint-action@v4 - with: - version: latest - skip-pkg-cache: true # golangci-lint can't work with this cache enabled, ref. https://github.com/golangci/golangci-lint-action/issues/135. - + uses: nspcc-dev/.github/.github/workflows/go-linter.yml@master gomodcheck: name: Check internal dependencies runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 3262aa4e4e..459a61908b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ testdata/ pkg/vm/testdata/fuzz !pkg/vm/testdata !pkg/wallet/testdata + +# Linter +.golangci.yml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index cd3800d31d..0000000000 --- a/.golangci.yml +++ /dev/null @@ -1,74 +0,0 @@ -# This file contains all available configuration options -# with their default values. - -# options for analysis running -run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 5m - - # include test files or not, default is true - tests: true - -# output configuration options -output: - # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - formats: - - format: tab - -# all available settings of specific linters -linters-settings: - exhaustive: - # indicates that switch statements are to be considered exhaustive if a - # 'default' case is present, even if all enum members aren't listed in the - # switch - default-signifies-exhaustive: true - -linters: - enable: - # mandatory linters - - govet - - revive - - # some default golangci-lint linters - - errcheck - - gosimple - - godot - - ineffassign - - staticcheck - - typecheck - - unused - - # extra linters - # - exhaustive - # - goconst - # - goerr113 - # - gomnd - # - nonamedreturns - # - unparam - - bidichk - - bodyclose - - contextcheck - - decorder - - durationcheck - - errorlint - - intrange - - copyloopvar - - gofmt - - misspell - - predeclared - - reassign - - whitespace - - goimports - disable-all: true - fast: false - -issues: - include: - - EXC0002 # should have a comment - - EXC0003 # test/Test ... consider calling this - - EXC0004 # govet - - EXC0005 # C-style breaks - exclude-rules: - - linters: - - revive - text: "unused-parameter" diff --git a/Makefile b/Makefile index ac51116590..82194ce041 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,10 @@ test: vet: @go vet ./... -lint: +.golangci.yml: + curl -L -o $@ https://github.com/nspcc-dev/.github/raw/master/.golangci.yml + +lint: .golangci.yml @golangci-lint run fmt: diff --git a/cli/cmdargs/parser.go b/cli/cmdargs/parser.go index 12cf6b1807..367a68baac 100644 --- a/cli/cmdargs/parser.go +++ b/cli/cmdargs/parser.go @@ -224,6 +224,7 @@ func parseCosigner(c string) (transaction.Signer, error) { res.AllowedGroups = append(res.AllowedGroups, pub) } + default: } } return res, nil diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index c0f670de3c..0b75167ffd 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -946,6 +946,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { expectedLen = 20 case smartcontract.Hash256Type: expectedLen = 32 + default: } if expectedLen != -1 && expectedLen != len(n.Elts) { c.prog.Err = fmt.Errorf("%s type must have size %d", tn.Obj().Name(), expectedLen) @@ -1225,10 +1226,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { case token.CONTINUE: post := c.getLabelOffset(labelPost, label) emit.Jmp(c.prog.BinWriter, opcode.JMPL, post) + default: + return nil } - return nil - case *ast.LabeledStmt: c.nextLabel = n.Label.Name @@ -1722,6 +1723,7 @@ func getJumpForToken(tok token.Token, typ types.Type) (opcode.Opcode, bool) { } return opcode.JMPNEL, true } + default: } return 0, false } @@ -2393,6 +2395,7 @@ func (c *codegen) writeJumps(b []byte) ([]byte, error) { return nil, fmt.Errorf("func '%s' has %d local variables (maximum is 255)", info.name, info.count) } b[nextIP-2] = byte(info.count) + default: } } @@ -2502,6 +2505,7 @@ func removeNOPs(b []byte, nopOffsets []int, sequencePoints map[string][]DebugSeq finallyOffset := int(int32(binary.LittleEndian.Uint32(arg))) finallyOffset += calcOffsetCorrection(ip, ip+finallyOffset, nopOffsets) binary.LittleEndian.PutUint32(arg, uint32(finallyOffset)) + default: } } diff --git a/pkg/compiler/inline_test.go b/pkg/compiler/inline_test.go index b3c21bcfbd..610ad979a5 100644 --- a/pkg/compiler/inline_test.go +++ b/pkg/compiler/inline_test.go @@ -47,6 +47,7 @@ func checkInstrCount(t *testing.T, src string, expectedSSlotCount, expectedCall, if ctx.IP() == mainStart && expectedLocalsMain >= 0 { require.Equal(t, expectedLocalsMain, int(param[0])) } + default: } if ctx.IP() == ctx.LenInstr() { break diff --git a/pkg/consensus/recovery_message.go b/pkg/consensus/recovery_message.go index 3f805f5a95..040add2b88 100644 --- a/pkg/consensus/recovery_message.go +++ b/pkg/consensus/recovery_message.go @@ -180,6 +180,7 @@ func (m *recoveryMessage) AddPayload(p dbft.ConsensusPayload[util.Uint256]) { Signature: p.GetCommit().(*commit).signature, InvocationScript: p.(*Payload).Witness.InvocationScript, }) + default: } } diff --git a/pkg/core/native/designate.go b/pkg/core/native/designate.go index b0d1f22967..de6a7b9be7 100644 --- a/pkg/core/native/designate.go +++ b/pkg/core/native/designate.go @@ -272,6 +272,7 @@ func (s *Designate) notifyRoleChanged(v *roleData, r noderoles.Role) { if s.StateRootService != nil { s.StateRootService.UpdateStateValidators(v.height, v.nodes.Copy()) } + default: } } diff --git a/pkg/core/native/native_test/cryptolib_test.go b/pkg/core/native/native_test/cryptolib_test.go index 1982f26da9..a8f14a8460 100644 --- a/pkg/core/native/native_test/cryptolib_test.go +++ b/pkg/core/native/native_test/cryptolib_test.go @@ -468,5 +468,5 @@ func TestVerifyGroth16Proof(t *testing.T) { publicWitness := make([]byte, fr.Bytes) // Verify. - validatorInvoker.Invoke(t, true, "verifyProof", argA, argB, argC, []interface{}{publicWitness}) + validatorInvoker.Invoke(t, true, "verifyProof", argA, argB, argC, []any{publicWitness}) } diff --git a/pkg/neorpc/rpcevent/filter.go b/pkg/neorpc/rpcevent/filter.go index 9b0bd0c69e..744b59f392 100644 --- a/pkg/neorpc/rpcevent/filter.go +++ b/pkg/neorpc/rpcevent/filter.go @@ -89,6 +89,7 @@ func Matches(f Comparator, r Container) bool { } } return senderOk && signerOK && typeOk + default: + return false } - return false } diff --git a/pkg/network/server.go b/pkg/network/server.go index 6c9c3df649..4916eb4d5c 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -1446,6 +1446,7 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error { return s.handlePong(peer, pong) case CMDVersion, CMDVerack: return fmt.Errorf("received '%s' after the handshake", msg.Command.String()) + default: } } else { switch msg.Command { diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 50d70d7f02..ea3fb47bae 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -536,6 +536,7 @@ func (s *Server) testHandleGetData(t *testing.T, invType payload.InventoryType, case CMDNotFound: require.Equal(t, notFound, msg.Payload.(*payload.Inventory).Hashes) recvNotFound.Store(true) + default: } } @@ -818,6 +819,7 @@ func TestHandleGetMPTData(t *testing.T) { case CMDMPTData: require.Equal(t, found, msg.Payload) recvResponse.Store(true) + default: } } hs := []util.Uint256{r1, r2} diff --git a/pkg/rpcclient/nns/contract_test.go b/pkg/rpcclient/nns/contract_test.go index 1e3e962323..5a1efe51db 100644 --- a/pkg/rpcclient/nns/contract_test.go +++ b/pkg/rpcclient/nns/contract_test.go @@ -582,8 +582,8 @@ func TestSetAdmin(t *testing.T) { testCases := []struct { name string setup func() - testFunc func() (interface{}, error) - want interface{} + testFunc func() (any, error) + want any wantErr bool }{ { @@ -591,9 +591,9 @@ func TestSetAdmin(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { txh, vub, err := c.SetAdmin(name, admin) - return []interface{}{txh, vub}, err + return []any{txh, vub}, err }, wantErr: true, }, @@ -604,11 +604,11 @@ func TestSetAdmin(t *testing.T) { ta.txh = txhMock ta.vub = 42 }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { txh, vub, err := c.SetAdmin(name, admin) - return []interface{}{txh, vub}, err + return []any{txh, vub}, err }, - want: []interface{}{txhMock, uint32(42)}, + want: []any{txhMock, uint32(42)}, }, { name: "SetAdminTransaction - Success", @@ -616,7 +616,7 @@ func TestSetAdmin(t *testing.T) { ta.err = nil ta.tx = txMock }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetAdminTransaction(name, admin) }, want: txMock, @@ -626,7 +626,7 @@ func TestSetAdmin(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetAdminTransaction(name, admin) }, wantErr: true, @@ -637,7 +637,7 @@ func TestSetAdmin(t *testing.T) { ta.err = nil ta.tx = txMock }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetAdminUnsigned(name, admin) }, want: txMock, @@ -647,7 +647,7 @@ func TestSetAdmin(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetAdminUnsigned(name, admin) }, wantErr: true, @@ -681,8 +681,8 @@ func TestSetRecord(t *testing.T) { testCases := []struct { name string setup func() - testFunc func() (interface{}, error) - want interface{} + testFunc func() (any, error) + want any wantErr bool }{ { @@ -690,9 +690,9 @@ func TestSetRecord(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { txh, vub, err := c.SetRecord(name, typev, data) - return []interface{}{txh, vub}, err + return []any{txh, vub}, err }, wantErr: true, }, @@ -703,11 +703,11 @@ func TestSetRecord(t *testing.T) { ta.txh = txhMock ta.vub = 42 }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { txh, vub, err := c.SetRecord(name, typev, data) - return []interface{}{txh, vub}, err + return []any{txh, vub}, err }, - want: []interface{}{txhMock, uint32(42)}, + want: []any{txhMock, uint32(42)}, }, { name: "SetRecordTransaction - Success", @@ -715,7 +715,7 @@ func TestSetRecord(t *testing.T) { ta.err = nil ta.tx = txMock }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetRecordTransaction(name, typev, data) }, want: txMock, @@ -725,7 +725,7 @@ func TestSetRecord(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetRecordTransaction(name, typev, data) }, wantErr: true, @@ -736,7 +736,7 @@ func TestSetRecord(t *testing.T) { ta.err = nil ta.tx = txMock }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetRecordUnsigned(name, typev, data) }, want: txMock, @@ -746,7 +746,7 @@ func TestSetRecord(t *testing.T) { setup: func() { ta.err = errors.New("test error") }, - testFunc: func() (interface{}, error) { + testFunc: func() (any, error) { return c.SetRecordUnsigned(name, typev, data) }, wantErr: true, diff --git a/pkg/services/notary/core_test.go b/pkg/services/notary/core_test.go index 65758da145..412e7346a8 100644 --- a/pkg/services/notary/core_test.go +++ b/pkg/services/notary/core_test.go @@ -232,6 +232,7 @@ func TestNotary(t *testing.T) { script, err = smartcontract.CreateMultiSigRedeemScript(requesters[i].m, pubs) require.NoError(t, err) nKeys += uint8(len(requesters[i].accounts)) + default: } signers[i] = transaction.Signer{ Account: hash.Hash160(script), @@ -294,6 +295,7 @@ func TestNotary(t *testing.T) { nSigs++ case notary.MultiSignature: nSigs += r.m + default: } } nSigners := len(requesters) + 1 diff --git a/pkg/services/oracle/jsonpath/jsonpath.go b/pkg/services/oracle/jsonpath/jsonpath.go index a43c7b62af..c46b270d0e 100644 --- a/pkg/services/oracle/jsonpath/jsonpath.go +++ b/pkg/services/oracle/jsonpath/jsonpath.go @@ -64,6 +64,7 @@ func Get(path string, value any) ([]any, bool) { objs, ok = p.processDot(objs) case pathLeftBracket: objs, ok = p.processLeftBracket(objs) + default: } if !ok || maxObjects < len(objs) { diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index 2098a89bab..f25beae045 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -2758,6 +2758,7 @@ func (s *Server) subscribe(reqParams params.Params, sub *subscriber) (any, *neor flt := new(neorpc.ExecutionFilter) err = jd.Decode(flt) filter = *flt + default: } if err != nil { return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, err.Error()) @@ -2832,6 +2833,7 @@ func (s *Server) subscribeToChannel(event neorpc.EventID) { s.chain.SubscribeForHeadersOfAddedBlocks(s.blockHeaderCh) } s.blockHeaderSubs++ + default: } } @@ -2892,6 +2894,7 @@ func (s *Server) unsubscribeFromChannel(event neorpc.EventID) { if s.blockHeaderSubs == 0 { s.chain.UnsubscribeFromHeadersOfAddedBlocks(s.blockHeaderCh) } + default: } } diff --git a/pkg/smartcontract/manifest/permission.go b/pkg/smartcontract/manifest/permission.go index 2543919812..c8ac08d826 100644 --- a/pkg/smartcontract/manifest/permission.go +++ b/pkg/smartcontract/manifest/permission.go @@ -105,8 +105,9 @@ func (d PermissionDesc) Compare(d1 PermissionDesc) int { return d.Hash().Compare(d1.Hash()) case PermissionGroup: return d.Group().Cmp(d1.Group()) + default: + return 0 // wildcard or type that we can't compare. } - return 0 // wildcard or type that we can't compare. } // Equals returns true if both PermissionDesc values are the same. diff --git a/pkg/smartcontract/param_type.go b/pkg/smartcontract/param_type.go index cb32c72ab6..80705ed7ea 100644 --- a/pkg/smartcontract/param_type.go +++ b/pkg/smartcontract/param_type.go @@ -175,7 +175,7 @@ func (pt ParamType) EncodeDefaultValue(w *io.BinWriter) { emit.Bytes(w, b[:Hash256Len]) case PublicKeyType: emit.Bytes(w, b[:PublicKeyLen]) - case ArrayType, MapType, InteropInterfaceType, VoidType: + case ArrayType, MapType, InteropInterfaceType, VoidType, UnknownType: } } diff --git a/pkg/smartcontract/rpcbinding/binding.go b/pkg/smartcontract/rpcbinding/binding.go index 7736e2ed6b..de8fb86683 100644 --- a/pkg/smartcontract/rpcbinding/binding.go +++ b/pkg/smartcontract/rpcbinding/binding.go @@ -564,8 +564,9 @@ func extendedTypeToGo(et binding.ExtendedType, named map[string]binding.Extended return "any", "" case smartcontract.VoidType: return "", "" + default: + panic("unreachable") } - panic("unreachable") } func etTypeConverter(et binding.ExtendedType, v string) string { @@ -686,8 +687,9 @@ func etTypeConverter(et binding.ExtendedType, v string) string { return "item.Value(), nil" case smartcontract.VoidType: return "" + default: + panic("unreachable") } - panic("unreachable") } func scTypeToGo(name string, typ smartcontract.ParamType, cfg *binding.Config) (string, string) { @@ -870,6 +872,7 @@ func addETImports(et binding.ExtendedType, named map[string]binding.ExtendedType case smartcontract.ArrayType: imports["errors"] = struct{}{} imports["fmt"] = struct{}{} + default: } if et.Value != nil { addETImports(*et.Value, named, imports) diff --git a/pkg/vm/contract_checks.go b/pkg/vm/contract_checks.go index 51bb68040c..6a1d053ed0 100644 --- a/pkg/vm/contract_checks.go +++ b/pkg/vm/contract_checks.go @@ -190,6 +190,7 @@ func IsScriptCorrect(script []byte, methods bitfield.Field) error { if typ == stackitem.AnyT && op != opcode.NEWARRAYT { return fmt.Errorf("using type ANY is incorrect at offset %d", ctx.ip) } + default: } } if !jumps.IsSubset(instrs) { diff --git a/pkg/vm/stackitem/json_test.go b/pkg/vm/stackitem/json_test.go index b8e6912570..c0f980fded 100644 --- a/pkg/vm/stackitem/json_test.go +++ b/pkg/vm/stackitem/json_test.go @@ -8,11 +8,11 @@ import ( "github.com/stretchr/testify/require" ) -func getTestDecodeFunc(js string, expected ...interface{}) func(t *testing.T) { +func getTestDecodeFunc(js string, expected ...any) func(t *testing.T) { return getTestDecodeEncodeFunc(js, true, expected...) } -func getTestDecodeEncodeFunc(js string, needEncode bool, expected ...interface{}) func(t *testing.T) { +func getTestDecodeEncodeFunc(js string, needEncode bool, expected ...any) func(t *testing.T) { return func(t *testing.T) { actual, err := FromJSON([]byte(js), 20, true) if expected[0] == nil { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index f9eac2e922..8db2004caa 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -914,6 +914,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro n = 4 case opcode.REVERSEN: n = toInt(v.estack.Pop().BigInt()) + default: } if err := v.estack.ReverseTop(n); err != nil { panic(err.Error()) @@ -1122,6 +1123,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res = cmp == 1 case opcode.GE: res = cmp >= 0 + default: } } v.estack.PushItem(stackitem.Bool(res))