diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5367d3f..f83de9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: binaryextension: .exe - image: [self-hosted, macos, arm64] name: macos-arm64 - - image: [self-hosted, linux, arm64] + - image: ubuntu-latest-arm-8-cores name: linux-arm64 env: BINARY_NAME: smcli${{ matrix.binaryextension }} @@ -38,7 +38,7 @@ jobs: go-version: ${{ env.go-version }} - name: Install required packages # only run on GH-hosted runner; self-hosted runner already has these - if: matrix.name == 'linux-amd64' + if: ${{ matrix.name == 'linux-amd64' || matrix.name == 'linux-arm64' }} run: sudo apt-get install -y libudev-dev - name: Build run: make build diff --git a/.golangci.yml b/.golangci.yml index 23d3bdc..5a2d2ea 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,14 @@ +# This file contains all available configuration options +# with their default values (in comments). +# +# This file is not a configuration example, +# it contains the exhaustive configuration with explanations of the options. + # Options for analysis running. run: - # The default concurrency value is the number of available CPU. + # Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously. + # If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota. + # Default: the number of logical CPUs in the machine # concurrency: 4 # Timeout for analysis, e.g. 30s, 5m. @@ -9,40 +17,18 @@ run: # Exit code when at least one issue was found. # Default: 1 - issues-exit-code: 1 + # issues-exit-code: 1 # Include test files or not. # Default: true - tests: true + # tests: true # List of build tags, all linters use it. - # Default: []. + # Default: [] # build-tags: - # - mytag + # - mytag - # Which dirs to skip: issues from them won't be reported. - # Can use regexp here: `generated.*`, regexp is applied on full path. - # Default value is empty list, - # but default dirs are skipped independently of this option's value (see skip-dirs-use-default). - # "/" will be replaced by current OS file path separator to properly work on Windows. - # skip-dirs: - # - src/external_libs - # - autogenerated_by_my_lib - # Enables skipping of directories: - # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ - # Default: true - skip-dirs-use-default: false - - # Which files to skip: they will be analyzed, but issues from them won't be reported. - # Default value is empty list, - # but there is no need to include all autogenerated files, - # we confidently recognize autogenerated files. - # If it's not please let us know. - # "/" will be replaced by current OS file path separator to properly work on Windows. - skip-files: - - "^mock_*\\.go$" - - # If set we pass it to "go list -mod={option}". From "go help modules": + # If set, we pass it to "go list -mod={option}". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit # automatic updating of go.mod described above. Instead, it fails when any changes # to go.mod are needed. This setting is most useful to check that go.mod does @@ -52,77 +38,410 @@ run: # the dependency descriptions in go.mod. # # Allowed values: readonly|vendor|mod - # By default, it isn't set. + # Default: "" modules-download-mode: readonly # Allow multiple parallel golangci-lint instances running. - # If false (default) - golangci-lint acquires file lock on start. - allow-parallel-runners: false + # If false, golangci-lint acquires file lock on start. + # Default: false + # allow-parallel-runners: true + + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + # allow-serial-runners: true # Define the Go version limit. # Mainly related to generics support since go1.18. - # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.18 + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 # go: '1.19' # output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number" - format: colored-line-number + # The formats used to render issues. + # Format: `colored-line-number`, `line-number`, `json`, `colored-tab`, `tab`, `checkstyle`, `code-climate`, `junit-xml`, `github-actions`, `teamcity` + # Output path can be either `stdout`, `stderr` or path to the file to write to. + # + # For the CLI flag (`--out-format`), multiple formats can be specified by separating them by comma. + # The output can be specified for each of them by separating format name and path by colon symbol. + # Example: "--out-format=checkstyle:report.xml,json:stdout,colored-line-number" + # The CLI flag (`--out-format`) override the configuration file. + # + # Default: + # formats: + # - format: colored-line-number + # path: stdout + formats: + # - format: json + # path: stderr + # - format: checkstyle + # path: report.xml + - format: colored-line-number + + # Print lines of code with issue. + # Default: true + # print-issued-lines: false - # print lines of code with issue, default is true - print-issued-lines: true + # Print linter name in the end of issue text. + # Default: true + # print-linter-name: false + + # Make issues output unique by line. + # Default: true + # uniq-by-line: false + + # Add a prefix to the output file references. + # Default: "" + # path-prefix: "" + + # Sort results by the order defined in `sort-order`. + # Default: false + sort-results: true + + # Order to use when sorting results. + # Require `sort-results` to `true`. + # Possible values: `file`, `linter`, and `severity`. + # + # If the severity values are inside the following list, they are ordered in this order: + # 1. error + # 2. warning + # 3. high + # 4. medium + # 5. low + # Either they are sorted alphabetically. + # + # Default: ["file"] + sort-order: + - linter + - severity + - file # filepath, line, and column. - # print linter name in the end of issue text, default is true - print-linter-name: true + # Show statistics per linter. + # Default: false + # show-stats: true + +linters: + # Disable all linters. + # Default: false + disable-all: true + # Enable specific linter + # https://golangci-lint.run/usage/linters/#enabled-by-default + enable: + # - asasalint + # - asciicheck + # - bidichk + # - bodyclose + # - containedctx + # - contextcheck + - copyloopvar + # - cyclop + # - decorder + - depguard + # - dogsled + # - dupl + # - dupword + # - durationcheck + # - errcheck + # - errchkjson + # - errname + # - errorlint + # - execinquery + # - exhaustive + # - exhaustruct + # - exportloopref + # - forbidigo + # - forcetypeassert + # - funlen + - gci + # - ginkgolinter + # - gocheckcompilerdirectives + # - gochecknoglobals + # - gochecknoinits + - gochecksumtype + # - gocognit + # - goconst + # - gocritic + # - gocyclo + - godot + # - godox + # - goerr113 + - gofmt + - gofumpt + # - goheader + # - goimports + # - gomnd + # - gomoddirectives + # - gomodguard + # - goprintffuncname + # - gosec + - gosimple + # - gosmopolitan + - govet + # - grouper + - importas + # - inamedparam + - ineffassign + # - interfacebloat + # - intrange + # - ireturn + - lll + # - loggercheck + # - maintidx + # - makezero + # - mirror + - misspell + # - musttag + - nakedret + - nestif + # - nilerr + # - nilnil + # - nlreturn + # - noctx + # - nolintlint + # - nonamedreturns + # - nosprintfhostport + # - paralleltest + - perfsprint + # - prealloc + # - predeclared + # - promlinter + # - protogetter + # - reassign + - revive + # - rowserrcheck + # - sloglint + - spancheck + # - sqlclosecheck + - staticcheck + # - stylecheck + # - tagalign + # - tagliatelle + # - tenv + # - testableexamples + - testifylint + # - testpackage + # - thelper + # - tparallel + - typecheck + # - unconvert + # - unparam + - unused + # - usestdlibvars + # - varnamelen + # - wastedassign + # - whitespace + # - wrapcheck + # - wsl + # - zerologlint + + # Enable all available linters. + # Default: false + # enable-all: true + # Disable specific linter + # https://golangci-lint.run/usage/linters/#disabled-by-default + # disable: + # - asasalint + # - asciicheck + # - bidichk + # - bodyclose + # - containedctx + # - contextcheck + # - copyloopvar + # - cyclop + # - decorder + # - depguard + # - dogsled + # - dupl + # - dupword + # - durationcheck + # - errcheck + # - errchkjson + # - errname + # - errorlint + # - execinquery + # - exhaustive + # - exhaustruct + # - exportloopref + # - forbidigo + # - forcetypeassert + # - funlen + # - gci + # - ginkgolinter + # - gocheckcompilerdirectives + # - gochecknoglobals + # - gochecknoinits + # - gochecksumtype + # - gocognit + # - goconst + # - gocritic + # - gocyclo + # - godot + # - godox + # - goerr113 + # - gofmt + # - gofumpt + # - goheader + # - goimports + # - gomnd + # - gomoddirectives + # - gomodguard + # - goprintffuncname + # - gosec + # - gosimple + # - gosmopolitan + # - govet + # - grouper + # - importas + # - inamedparam + # - ineffassign + # - interfacebloat + # - intrange + # - ireturn + # - lll + # - loggercheck + # - maintidx + # - makezero + # - mirror + # - misspell + # - musttag + # - nakedret + # - nestif + # - nilerr + # - nilnil + # - nlreturn + # - noctx + # - nolintlint + # - nonamedreturns + # - nosprintfhostport + # - paralleltest + # - perfsprint + # - prealloc + # - predeclared + # - promlinter + # - protogetter + # - reassign + # - revive + # - rowserrcheck + # - sloglint + # - spancheck + # - sqlclosecheck + # - staticcheck + # - stylecheck + # - tagalign + # - tagliatelle + # - tenv + # - testableexamples + # - testifylint + # - testpackage + # - thelper + # - tparallel + # - typecheck + # - unconvert + # - unparam + # - unused + # - usestdlibvars + # - varnamelen + # - wastedassign + # - whitespace + # - wrapcheck + # - wsl + # - zerologlint + + # Enable presets. + # https://golangci-lint.run/usage/linters + # Default: [] + # presets: + # - bugs + # - comment + # - complexity + # - error + # - format + # - import + # - metalinter + # - module + # - performance + # - sql + # - style + # - test + # - unused + + # Enable only fast linters from enabled linters set (first run won't be fast) + # Default: false + # fast: true # All available settings of specific linters. linters-settings: - staticcheck: - # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks - # Default: ["*"] - checks: ["all"] - - errcheck: - # Report about not checking of errors in type assertions: `a := b.(MyStruct)`. - # Such cases aren't reported by default. - # Default: false - check-type-assertions: true + depguard: + # Rules to apply. + # + # Variables: + # - File Variables + # you can still use and exclamation mark ! in front of a variable to say not to use it. + # Example !$test will match any file that is not a go test file. + # + # `$all` - matches all go files + # `$test` - matches all go test files + # + # - Package Variables + # + # `$gostd` - matches all of go's standard library (Pulled from `GOROOT`) + # + # Default: Only allow $gostd in all files. + rules: + # Name of a rule. + main: + # Used to determine the package matching priority. + # There are three different modes: `original`, `strict`, and `lax`. + # Default: "original" + # list-mode: lax + # List of file globs that will match this list of settings to compare against. + # Default: $all + # files: + # - "!**/*_a _file.go" + # List of allowed packages. + # allow: + # - $gostd + # - github.com/OpenPeeDeeP + # Packages that are not allowed where the value is a suggestion. + deny: + - pkg: "io/ioutil" + desc: Use os instead + - pkg: "github.com/pkg/errors" + desc: Should be replaced by standard lib errors package + - pkg: "golang.org/x/xerrors" + desc: Should be replaced by standard lib errors package + - pkg: "golang.org/x/net/context" + desc: Should be replaced by standard lib context package + - pkg: "golang.org/x/crypto/ed25519" + desc: Should be replaced by standard lib ed25519 package - # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`. - # Such cases aren't reported by default. - # Default: false - check-blank: true + gci: + # Section configuration to compare against. + # Section names are case-insensitive and may contain parameters in (). + # The default order of sections is `standard > default > custom > blank > dot > alias`, + # If `custom-order` is `true`, it follows the order of `sections` option. + # Default: ["standard", "default"] + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/spacemeshos/smcli) # Custom section: groups all imports with the specified Prefix. + # - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + # - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. + # - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled. + + # Skip generated files. + # Default: true + # skip-generated: false - govet: - # Report about shadowed variables. - # Default: false - check-shadowing: false - # Disable all analyzers. - # Default: false - disable-all: false - # Enable analyzers by name (in addition to default). - # Run `go tool vet help` to see all analyzers. - # Default: [] - # enable: - # Enable all analyzers. + # Enable custom order of sections. + # If `true`, make the section order the same as the order of `sections`. # Default: false - enable-all: false - # Disable analyzers by name. - # Run `go tool vet help` to see all analyzers. - # Default: [] - # disable: - - revive: - # Sets the default failure confidence. - # This means that linting errors with less than 0.8 confidence will be ignored. - # Default: 0.8 - confidence: 0.8 + # custom-order: true gofmt: # Simplify code: gofmt with `-s` option. # Default: true - simplify: true - + # simplify: false # Apply the rewrite rules to the source before reformatting. # https://pkg.go.dev/cmd/gofmt # Default: [] @@ -132,98 +451,60 @@ linters-settings: - pattern: "a[b:len(a)]" replacement: "a[b:]" - gocyclo: - # Minimal code complexity to report. - # Default: 30 (but we recommend 10-20) - min-complexity: 10 - - goconst: - # Minimal length of string constant. - # Default: 3 - min-len: 3 + gofumpt: + # Module path which contains the source code being formatted. + # Default: "" + # module-path: github.com/org/project - # Minimum occurrences of constant string count to trigger issue. - # Default: 3 - min-occurrences: 3 + # Choose whether to use the extra rules. + # Default: false + extra-rules: true - depguard: - # Kind of list is passed in. - # Allowed values: allowlist|denylist - # Default: denylist - list-type: denylist + gosimple: + # Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: ["all"] - # Check the list against standard lib. + govet: + # Disable all analyzers. # Default: false - include-go-root: true - - # A list of packages for the list type specified. - # Can accept both string prefixes and string glob patterns. + disable-all: false + # Enable analyzers by name. + # (in addition to default: + # appends, asmdecl, assign, atomic, bools, buildtag, cgocall, composites, copylocks, defers, directive, errorsas, + # framepointer, httpresponse, ifaceassert, loopclosure, lostcancel, nilfunc, printf, shift, sigchanyzer, slog, + # stdmethods, stringintconv, structtag, testinggoroutine, tests, timeformat, unmarshal, unreachable, unsafeptr, + # unusedresult + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. # Default: [] - packages: - - "io/ioutil" - - "github.com/pkg/errors" - - "golang.org/x/xerrors" - - "golang.org/x/net/context" - - "golang.org/x/crypto/ed25519" - - misspell: - # Correct spellings using locale preferences for US or UK. - # Setting locale to US will correct the British spelling of 'colour' to 'color'. - # Default is to use a neutral variety of English. - locale: US - - lll: - # Max line length, lines longer will be reported. - # '\t' is counted as 1 character by default, and can be changed with the tab-width option. - # Default: 120. - line-length: 120 - # Tab width in spaces. - # Default: 1 - tab-width: 4 - - nakedret: - # Make an issue if func has more lines of code than this setting, and it has naked returns. - # Default: 30 - max-func-lines: 30 - - prealloc: - # IMPORTANT: we don't recommend using this linter before doing performance profiling. - # For most programs usage of prealloc will be a premature optimization. + # enable: - # Report pre-allocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. - # Default: true - simple: true - # Report pre-allocation suggestions on range loops. - # Default: true - range-loops: true - # Report pre-allocation suggestions on for loops. + # Enable all analyzers. # Default: false - for-loops: true - - gci: - # Section configuration to compare against. - # Section names are case-insensitive and may contain parameters in (). - # The default order of sections is `standard > default > custom > blank > dot`, - # If `custom-order` is `true`, it follows the order of `sections` option. - # Default: ["standard", "default"] - sections: - - standard - - default - - prefix(github.com/spacemeshos/smcli) + enable-all: false + # Disable analyzers by name. + # (in addition to default + # atomicalign, deepequalerrors, fieldalignment, findcall, nilness, reflectvaluecompare, shadow, sortslice, + # timeformat, unusedwrite + # ). + # Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. + # Default: [] + # disable: importas: # Do not allow unaliased imports of aliased packages. # Default: false - no-unaliased: false + # no-unaliased: true # Do not allow non-required aliases. # Default: false - no-extra-aliases: false + # no-extra-aliases: true # List of aliases # Default: [] alias: - pkg: "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" alias: chaos - - pkg: "github.com/hashicorp/golang-lru" + - pkg: "github.com/hashicorp/golang-lru/v2" alias: lru - pkg: "github.com/grpc-ecosystem/go-grpc-middleware" alias: grpcmw @@ -234,7 +515,7 @@ linters-settings: - pkg: "github.com/libp2p/go-libp2p-pubsub" alias: pubsub - pkg: "github.com/libp2p/go-libp2p-pubsub/pb" - alias: pb + alias: pubsubpb - pkg: "github.com/libp2p/go-libp2p/p2p/net/mock" alias: mocknet - pkg: "github.com/libp2p/go-libp2p-testing/netutil" @@ -249,8 +530,6 @@ linters-settings: alias: vm - pkg: "github.com/spacemeshos/go-spacemesh/p2p/metrics" alias: p2pmetrics - - pkg: "github.com/spacemeshos/go-spacemesh/sql/proposals" - alias: dbproposals - pkg: "github.com/spacemeshos/go-spacemesh/sql/metrics" alias: dbmetrics - pkg: "github.com/spacemeshos/go-spacemesh/txs/types" @@ -270,114 +549,166 @@ linters-settings: - pkg: "k8s.io/client-go/applyconfigurations/meta/v1" alias: metav1 - godot: - # Comments to be checked: `declarations`, `toplevel`, or `all`. - # Default: declarations - scope: declarations - # List of regexps for excluding particular comment lines from check. + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 120 + # Tab width in spaces. + # Default: 1 + tab-width: 4 + + misspell: + # Correct spellings using locale preferences for US or UK. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + # Default is to use a neutral variety of English. + locale: US + # Typos to ignore. + # Should be in lower case. + # Default: [] + # ignore-words: + # - someword + # Extra word corrections. + # `typo` and `correction` should only contain letters. + # The words are case-insensitive. # Default: [] - exclude: - # Exclude todo and fixme comments. - - "^FIXME:" - - "^TODO:" - # Check that each sentence ends with a period. + extra-words: + - typo: "iff" + correction: "if" + - typo: "cancelation" + correction: "cancellation" + # Mode of the analysis: + # - default: checks all the file content. + # - restricted: checks only comments. + # Default: "" + mode: restricted + + nakedret: + # Make an issue if func has more lines of code than this setting, and it has naked returns. + # Default: 30 + max-func-lines: 30 + + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 15 + + perfsprint: + # Optimizes even if it requires an int or uint type cast. # Default: true - period: true - # Check that each sentence starts with a capital letter. + # int-conversion: false + # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. # Default: false - capital: false + err-error: true + # Optimizes `fmt.Errorf`. + # Default: true + # errorf: false + # Optimizes `fmt.Sprintf` with only one argument. + # Default: true + # sprintf1: false + # Optimizes into strings concatenation. + # Default: true + strconcat: false - gofumpt: - # Choose whether to use the extra rules. - # Default: false - extra-rules: false - - gosec: - # To select a subset of rules to run. - # Available rules: https://github.com/securego/gosec#available-rules - # Default: [] - means include all rules - # includes: - # To specify a set of rules to explicitly exclude. - # Available rules: https://github.com/securego/gosec#available-rules - # Default: [] - # excludes: - # Exclude generated files - # Default: false - exclude-generated: false - # Filter out the issues with a lower severity than the given value. - # Valid options are: low, medium, high. - # Default: low - severity: medium - # Filter out the issues with a lower confidence than the given value. - # Valid options are: low, medium, high. - # Default: low - confidence: medium - # Concurrency value. - # Default: the number of logical CPUs usable by the current process. - concurrency: 12 - - whitespace: - # Enforces newlines (or comments) after every multi-line if statement. - # Default: false - multi-if: true - # Enforces newlines (or comments) after every multi-line function signature. + revive: + # Maximum number of open files at the same time. + # See https://github.com/mgechev/revive#command-line-flags + # Defaults to unlimited. + max-open-files: 2048 + + # When set to false, ignores files with "GENERATED" header, similar to golint. + # See https://github.com/mgechev/revive#available-rules for details. # Default: false - multi-func: true - - wrapcheck: - # An array of strings that specify substrings of signatures to ignore. - # If this set, it will override the default set of ignored signatures. - # See https://github.com/tomarrell/wrapcheck#configuration for more information. - # Default: [".Errorf(", "errors.New(", "errors.Unwrap(", ".Wrap(", ".Wrapf(", ".WithMessage(", ".WithMessagef(", ".WithStack("] - ignoreSigs: - - .Errorf( - - errors.New( - - .WithMessage( - - .WithMessagef( - - .WithStack( + ignore-generated-header: true -linters: - # Disable all linters. - # Default: false - disable-all: true - # Enable specific linter - # https://golangci-lint.run/usage/linters/#enabled-by-default - enable: - - gci - - importas - - govet - - godot - - gofmt - - gofumpt - - revive - - misspell - - staticcheck - - unused - - ineffassign - - typecheck - - nakedret - - depguard - - goconst - # - whitespace - # - wrapcheck - # - errcheck - # - gosec - # - nakedret - # - gocyclo - # - lll - # - prealloc + # Sets the default severity. + # See https://github.com/mgechev/revive#configuration + # Default: warning + # severity: error - # Enable all available linters. - # Default: false - enable-all: false + # Enable all available rules. + # Default: false + # enable-all-rules: true - # Disable specific linter - # https://golangci-lint.run/usage/linters/#disabled-by-default - # disable: + # Sets the default failure confidence. + # This means that linting errors with less than 0.8 confidence will be ignored. + # Default: 0.8 + # confidence: 0.8 + + spancheck: + # Checks to enable. + # Options include: + # - `end`: check that `span.End()` is called + # - `record-error`: check that `span.RecordError(err)` is called when an error is returned + # - `set-status`: check that `span.SetStatus(codes.Error, msg)` is called when an error is returned + # Default: ["end"] + checks: + - end + - record-error + - set-status + # A list of regexes for function signatures that silence `record-error` and `set-status` reports + # if found in the call path to a returned error. + # https://github.com/jjti/go-spancheck#ignore-check-signatures + # Default: [] + ignore-check-signatures: + - "telemetry.RecordError" - # Run only fast linters from enabled linters set (first run won't be fast) - # Default: false - fast: false + staticcheck: + # SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks + # Default: ["*"] + checks: ["all"] + + testifylint: + # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + enable-all: true + # Disable checkers by name + # (in addition to default + # suite-thelper + # ). + # disable: + # - blank-import + # - bool-compare + # - compares + # - empty + # - error-is-as + # - error-nil + # - expected-actual + # - go-require + # - float-compare + # - len + # - nil-compare + # - require-error + # - suite-dont-use-pkg + # - suite-extra-assert-call + # - suite-thelper + # - useless-assert + + # Disable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + # disable-all: true + # Enable checkers by name + # (in addition to default + # blank-import, bool-compare, compares, empty, error-is-as, error-nil, expected-actual, go-require, float-compare, + # len, nil-compare, require-error, suite-dont-use-pkg, suite-extra-assert-call, useless-assert + # ). + # enable: + # - blank-import + # - bool-compare + # - compares + # - empty + # - error-is-as + # - error-nil + # - expected-actual + # - go-require + # - float-compare + # - len + # - nil-compare + # - require-error + # - suite-dont-use-pkg + # - suite-extra-assert-call + # - suite-thelper + # - useless-assert issues: # List of regexps of issue texts to exclude. @@ -388,19 +719,77 @@ issues: # # Default: https://golangci-lint.run/usage/false-positives/#default-exclusions # exclude: + # - abcdef # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - - linters: - - staticcheck - text: SA1019 + # exclude-rules: # Independently of option `exclude` we use default exclude patterns, # it can be disabled by this option. # To list all excluded by default patterns execute `golangci-lint run --help`. - # Default: true. + # Default: true exclude-use-default: false + # If set to true, `exclude` and `exclude-rules` regular expressions become case-sensitive. + # Default: false + exclude-case-sensitive: false + + # Which dirs to exclude: issues from them won't be reported. + # Can use regexp here: `generated.*`, regexp is applied on full path, + # including the path prefix if one is set. + # Default dirs are skipped independently of this option's value (see exclude-dirs-use-default). + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + # exclude-dirs: + # - src/external_libs + # - autogenerated_by_my_lib + + # Enables exclude of directories: + # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ + # Default: true + exclude-dirs-use-default: false + + # Which files to exclude: they will be analyzed, but issues from them won't be reported. + # There is no need to include all autogenerated files, + # we confidently recognize autogenerated files. + # If it's not, please let us know. + # "/" will be replaced by current OS file path separator to properly work on Windows. + # Default: [] + exclude-files: + - "^mock_*\\.go$" + + # To follow strictly the Go generated file convention. + # + # If set to true, 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 + # + # By default, a lax pattern is applied: + # sources are excluded if they contain lines `autogenerated file`, `code generated`, `do not edit`, etc. + # Default: false + # exclude-generated-strict: true + + # The list of ids of default excludes to include or disable. + # https://golangci-lint.run/usage/false-positives/#default-exclusions + # Default: [] + # include: + # - EXC0001 + # - EXC0002 + # - EXC0003 + # - EXC0004 + # - EXC0005 + # - EXC0006 + # - EXC0007 + # - EXC0008 + # - EXC0009 + # - EXC0010 + # - EXC0011 + # - EXC0012 + # - EXC0013 + # - EXC0014 + # - EXC0015 + # Maximum issues count per one linter. # Set to 0 to disable. # Default: 50 @@ -417,5 +806,55 @@ issues: # It's not practical to fix all existing issues at the moment of integration: # much better don't allow issues in new code. # - # Default: false. - new: false + # Default: false + # new: true + + # Show only new issues created after git revision `REV`. + # Default: "" + # new-from-rev: HEAD + + # Show only new issues created in git patch with set file path. + # Default: "" + # new-from-patch: path/to/patch/file + + # Fix found issues (if it's supported by the linter). + # Default: false + # fix: true + + # Show issues in any part of update files (requires new-from-rev or new-from-patch). + # Default: false + whole-files: true + +severity: + # Set the default severity for issues. + # + # If severity rules are defined and the issues do not match or no severity is provided to the rule + # this will be the default severity applied. + # Severities should match the supported severity names of the selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#SeverityLevel + # - GitHub: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + # - TeamCity: https://www.jetbrains.com/help/teamcity/service-messages.html#Inspection+Instance + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Default: "" + default-severity: error + + # If set to true `severity-rules` regular expressions become case-sensitive. + # Default: false + case-sensitive: true + + # When a list of severity rules are provided, severity information will be added to lint issues. + # Severity rules have the same filtering capability as exclude rules + # except you are allowed to specify one matcher per severity rule. + # + # `@linter` can be used as severity value to keep the severity from linters (e.g. revive, gosec, ...) + # + # Only affects out formats that support setting severity information. + # + # Default: [] + # rules: + # - linters: + # - dupl + # severity: info diff --git a/cmd/genesis.go b/cmd/genesis.go index e3b1e81..1b3432b 100644 --- a/cmd/genesis.go +++ b/cmd/genesis.go @@ -31,8 +31,9 @@ var verifyCmd = &cobra.Command{ // first, collect the keys var keys []core.PublicKey - fmt.Print("First, let's collect your public keys. Keys must be entered in hex format: 64 characters, without 0x prefix.\n") - fmt.Print("Enter pubkeys one at a time; press enter again when done: ") + fmt.Print("First, let's collect your public keys. ") + fmt.Print("Keys must be entered in hex format: 64 characters, without 0x prefix.\n") + fmt.Print("Enter pub keys one at a time; press enter again when done: ") for { var keyStr string _, err := fmt.Scanln(&keyStr) diff --git a/cmd/wallet.go b/cmd/wallet.go index e26de68..a61fc98 100644 --- a/cmd/wallet.go +++ b/cmd/wallet.go @@ -83,7 +83,8 @@ sure the device is connected, unlocked, and the Spacemesh app is open.`, text, err := password.Read(os.Stdin) fmt.Println() cobra.CheckErr(err) - fmt.Println("Note: This application does not yet support BIP-39-compatible optional passwords. Support will be added soon.") + fmt.Print("Note: This application does not yet support BIP-39-compatible optional passwords. ") + fmt.Println("Support will be added soon.") // It's critical that we trim whitespace, including CRLF. Otherwise it will get included in the mnemonic. text = strings.TrimSpace(text) @@ -91,9 +92,12 @@ sure the device is connected, unlocked, and the Spacemesh app is open.`, if text == "" { w, err = wallet.NewMultiWalletRandomMnemonic(n) cobra.CheckErr(err) - fmt.Println("\nThis is your mnemonic (seed phrase). Write it down and store it safely. It is the ONLY way to restore your wallet.") - fmt.Println("Neither Spacemesh nor anyone else can help you restore your wallet without this mnemonic.") - fmt.Println("\n***********************************\nSAVE THIS MNEMONIC IN A SAFE PLACE!\n***********************************") + fmt.Print("\nThis is your mnemonic (seed phrase). Write it down and store it safely.") + fmt.Print("It is the ONLY way to restore your wallet.\n") + fmt.Print("Neither Spacemesh nor anyone else can help you restore your wallet without this mnemonic.\n") + fmt.Print("\n***********************************\n") + fmt.Print("SAVE THIS MNEMONIC IN A SAFE PLACE!") + fmt.Print("\n***********************************\n") fmt.Println() fmt.Println(w.Mnemonic()) fmt.Println("\nPress enter when you have securely saved your mnemonic.") diff --git a/wallet/bip32.go b/wallet/bip32.go index 10d7c53..d8485ab 100644 --- a/wallet/bip32.go +++ b/wallet/bip32.go @@ -4,6 +4,7 @@ import ( "crypto/ed25519" "encoding/hex" "encoding/json" + "errors" "fmt" smbip32 "github.com/spacemeshos/smkeys/bip32" @@ -95,7 +96,7 @@ func (kp *EDKeyPair) NewChildKeyPair(seed []byte, childIdx int) (*EDKeyPair, err Path: path, }, nil default: - return nil, fmt.Errorf("unknown key type") + return nil, errors.New("unknown key type") } } @@ -109,7 +110,7 @@ func pubkeyFromLedger(path HDPath, master bool) (*EDKeyPair, error) { // the one they really care about, which is the first child key. key, err := ledger.ReadPubkeyFromLedger("", HDPathToString(path), !master) if err != nil { - return nil, fmt.Errorf("error reading pubkey from ledger. Are you sure it's connected, unlocked, and the Spacemesh app is open? err: %w", err) + return nil, fmt.Errorf("error reading pubkey from ledger: %w", err) } name := "Ledger Master Key" diff --git a/wallet/bip32_test.go b/wallet/bip32_test.go index 077eb88..e002fc6 100644 --- a/wallet/bip32_test.go +++ b/wallet/bip32_test.go @@ -45,8 +45,8 @@ func TestChildKeyPair(t *testing.T) { require.NoError(t, err) childKeyPair1, err := masterKeyPair.NewChildKeyPair(goodSeed, 0) require.Equal(t, path, childKeyPair1.Path) - require.Equal(t, ed25519.PrivateKeySize, len(childKeyPair1.Private)) - require.Equal(t, ed25519.PublicKeySize, len(childKeyPair1.Public)) + require.Len(t, childKeyPair1.Private, ed25519.PrivateKeySize) + require.Len(t, childKeyPair1.Public, ed25519.PublicKeySize) require.NoError(t, err) require.NotEmpty(t, childKeyPair1) @@ -59,17 +59,18 @@ func TestChildKeyPair(t *testing.T) { // generate second keypair and check lengths childKeyPair2, err := bip32.Derive(HDPathToString(path), goodSeed) require.NoError(t, err) - require.Equal(t, ed25519.PrivateKeySize, len(childKeyPair2)) + require.Len(t, childKeyPair2, ed25519.PrivateKeySize) privkey2 := PrivateKey(childKeyPair2[:]) - require.Equal(t, ed25519.PrivateKeySize, len(privkey2)) + require.Len(t, privkey2, ed25519.PrivateKeySize) edpubkey2 := ed25519.PrivateKey(privkey2).Public().(ed25519.PublicKey) - require.Equal(t, ed25519.PublicKeySize, len(edpubkey2)) + require.Len(t, edpubkey2, ed25519.PublicKeySize) pubkey2 := PublicKey(edpubkey2) - require.Equal(t, ed25519.PublicKeySize, len(pubkey2)) + require.Len(t, pubkey2, ed25519.PublicKeySize) // make sure they agree require.Equal(t, "feae6977b42bf3441d04314d09c72c5d6f2d1cb4bf94834680785b819f8738dd", hex.EncodeToString(pubkey2)) require.Equal(t, hex.EncodeToString(childKeyPair1.Public), hex.EncodeToString(pubkey2)) + //nolint:lll require.Equal(t, "05fe9affa5562ca833faf3803ce5f6f7615d3c37c4a27903492027f6853e486dfeae6977b42bf3441d04314d09c72c5d6f2d1cb4bf94834680785b819f8738dd", hex.EncodeToString(privkey2)) require.Equal(t, hex.EncodeToString(childKeyPair1.Private), hex.EncodeToString(privkey2)) } diff --git a/wallet/bip44.go b/wallet/bip44.go index 04249fb..5904137 100644 --- a/wallet/bip44.go +++ b/wallet/bip44.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "regexp" + "strconv" + "strings" ) //lint:file-ignore SA4016 ignore ineffective bitwise operations to aid readability @@ -128,15 +130,18 @@ func IsPathCompletelyHardened(path HDPath) bool { // HDPathToString converts a BIP44 HD path to a string of the form // "m/44'/540'/account'/chain'/address_index'". func HDPathToString(path HDPath) string { - s := "m" + var sb strings.Builder + sb.WriteString("m") for _, p := range path { + sb.WriteString("/") if p >= BIP32HardenedKeyStart { - s += "/" + fmt.Sprint(p-BIP32HardenedKeyStart) + "'" + sb.WriteString(strconv.FormatUint(uint64(p-BIP32HardenedKeyStart), 10)) + sb.WriteString("'") } else { - s += "/" + fmt.Sprint(p) + sb.WriteString(strconv.FormatUint(uint64(p), 10)) } } - return s + return sb.String() } func parseUint(s string) uint { diff --git a/wallet/bip44_test.go b/wallet/bip44_test.go index e398d7d..c030d31 100644 --- a/wallet/bip44_test.go +++ b/wallet/bip44_test.go @@ -16,12 +16,33 @@ func TestStringToHDPath(t *testing.T) { path string expected HDPath }{ - {"m/44'/540'", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540}}, - {"m/44'/540'/0", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, 0}}, - {"m/44'/540'/0'/0'/0'", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart, BIP32HardenedKeyStart, BIP32HardenedKeyStart}}, - {"m/44'/540'/0'/0/0", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart, 0, 0}}, - {"m/44'/540'/0/0'/0", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, 0, BIP32HardenedKeyStart, 0}}, - {"m/44'/540'/2'/0/0", HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart | 2, 0, 0}}, + { + "m/44'/540'", + HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540}, + }, + { + "m/44'/540'/0", + HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, 0}, + }, + { + "m/44'/540'/0'/0'/0'", + HDPath{ + BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart, + BIP32HardenedKeyStart, BIP32HardenedKeyStart, + }, + }, + { + "m/44'/540'/0'/0/0", + HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart, 0, 0}, + }, + { + "m/44'/540'/0/0'/0", + HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, 0, BIP32HardenedKeyStart, 0}, + }, + { + "m/44'/540'/2'/0/0", + HDPath{BIP32HardenedKeyStart | 44, BIP32HardenedKeyStart | 540, BIP32HardenedKeyStart | 2, 0, 0}, + }, } for _, tv := range testVectors { diff --git a/wallet/store.go b/wallet/store.go index 4213e10..9b18421 100644 --- a/wallet/store.go +++ b/wallet/store.go @@ -8,7 +8,7 @@ import ( "crypto/rand" "crypto/sha512" "encoding/json" - "fmt" + "errors" "io" "log" @@ -126,7 +126,7 @@ func WithPbkdf2Password(password []byte) WalletKeyOpt { } // https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html#71-encryption-types-to-use -func (k *WalletKey) encrypt(plaintext []byte) (ciphertext []byte, nonce []byte, err error) { +func (k *WalletKey) encrypt(plaintext []byte) (ciphertext, nonce []byte, err error) { block, err := aes.NewCipher(k.key) if err != nil { return @@ -146,7 +146,7 @@ func (k *WalletKey) encrypt(plaintext []byte) (ciphertext []byte, nonce []byte, return } -func (k *WalletKey) decrypt(ciphertext []byte, nonce []byte) (plaintext []byte, err error) { +func (k *WalletKey) decrypt(ciphertext, nonce []byte) (plaintext []byte, err error) { block, err := aes.NewCipher(k.key) if err != nil { return @@ -171,7 +171,7 @@ func (k *WalletKey) Open(file io.Reader, debugMode bool) (*Wallet, error) { var salt [Pbkdf2SaltBytesLen]byte copy(salt[:], ew.Secrets.KDFParams.Salt) if !bytes.Equal(salt[:], ew.Secrets.KDFParams.Salt) { - return nil, fmt.Errorf("error reading encrypted wallet file salt, check salt length") + return nil, errors.New("error reading encrypted wallet file salt, check salt length") } WithSalt(salt)(k) } else if !bytes.Equal(ew.Secrets.KDFParams.Salt, k.salt) { @@ -206,15 +206,15 @@ func (k *WalletKey) Open(file io.Reader, debugMode bool) (*Wallet, error) { return w, nil } -func (k *WalletKey) Export(file io.Writer, w *Wallet) (err error) { +func (k *WalletKey) Export(file io.Writer, w *Wallet) error { // encrypt the secrets plaintext, err := json.Marshal(w.Secrets) if err != nil { - return + return err } ciphertext, nonce, err := k.encrypt(plaintext) if err != nil { - return + return err } ew := &EncryptedWalletFile{ Meta: w.Meta, diff --git a/wallet/wallet.go b/wallet/wallet.go index 5849d21..26d855a 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -4,6 +4,7 @@ import ( "crypto/ed25519" "encoding/hex" "encoding/json" + "errors" "fmt" "strings" @@ -15,7 +16,7 @@ import ( "github.com/spacemeshos/smcli/common" ) -var errWhitespace = fmt.Errorf("whitespace violation in mnemonic phrase") +var errWhitespace = errors.New("whitespace violation in mnemonic phrase") // Wallet is the basic data structure. type Wallet struct { @@ -95,7 +96,7 @@ func NewMultiWalletRandomMnemonic(n int) (*Wallet, error) { func NewMultiWalletFromMnemonic(m string, n int) (*Wallet, error) { if n < 0 || n > common.MaxAccountsPerWallet { - return nil, fmt.Errorf("invalid number of accounts") + return nil, errors.New("invalid number of accounts") } // bip39 lib doesn't properly validate whitespace so we have to do that manually. @@ -105,7 +106,7 @@ func NewMultiWalletFromMnemonic(m string, n int) (*Wallet, error) { // this checks the number of words and the checksum. if !bip39.IsMnemonicValid(m) { - return nil, fmt.Errorf("invalid mnemonic") + return nil, errors.New("invalid mnemonic") } // TODO: add option for user to provide passphrase @@ -125,10 +126,12 @@ func NewMultiWalletFromMnemonic(m string, n int) (*Wallet, error) { func NewMultiWalletFromLedger(n int) (*Wallet, error) { if n < 0 || n > common.MaxAccountsPerWallet { - return nil, fmt.Errorf("invalid number of accounts") + return nil, errors.New("invalid number of accounts") } masterKeyPair, err := NewMasterKeyPairFromLedger() if err != nil { + fmt.Println("Error: ", err) + fmt.Println("Are you sure the ledger is connected, unlocked, and the Spacemesh app is open?") return nil, err } // seed is not used in case of ledger diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 663c82a..284a1c3 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -42,6 +42,7 @@ func TestAccountFromSeed(t *testing.T) { keypair := accts[0] expPubKey := "feae6977b42bf3441d04314d09c72c5d6f2d1cb4bf94834680785b819f8738dd" + //nolint:lll expPrivKey := "05fe9affa5562ca833faf3803ce5f6f7615d3c37c4a27903492027f6853e486dfeae6977b42bf3441d04314d09c72c5d6f2d1cb4bf94834680785b819f8738dd" actualPubKey := hex.EncodeToString(keypair.Public) @@ -77,6 +78,7 @@ func TestWalletFromGivenMnemonic(t *testing.T) { w, err := NewMultiWalletFromMnemonic(mnemonic, 1) require.NoError(t, err) expPubKey := "de30fc9b812248583da6259433626fcdd2cb5ce589b00047b81e127950b9bca6" + //nolint:lll expPrivKey := "cd85df73aa3bc31de2f0b69bb1421df7eb0cdca7cb170a457869ab337749dae1de30fc9b812248583da6259433626fcdd2cb5ce589b00047b81e127950b9bca6" actualPubKey := hex.EncodeToString(w.Secrets.Accounts[0].Public)